【发布时间】:2018-02-14 00:23:39
【问题描述】:
我一直在尝试将两个哈希值相互比较。不幸的是,即使得到了这里的大力帮助,我也很难把我想做的事情集中起来。
所以,我再次求助于互联网搜索,我很幸运找到了 Edxi 的代码(完全归功于他和 Dbroeglin,他似乎是最初编写的)
https://gist.github.com/edxi/87cb8a550b43ec90e4a89d2e69324806
他的 compare-hash 函数在比较方面完全符合我的需要。但是,我想在最终输出中报告哈希的完整路径。所以我试图更新代码以允许这样做。我的想法是我应该能够在代码自行循环时获取密钥(又名路径),但我显然是以错误的方式处理它。
我是否采用正确的方法来解决这个问题,如果没有,有人会建议另一种方法吗?到目前为止我发现的最大问题是,如果我更改哈希,我的代码更改将不起作用,例如添加'More' = 'stuff' 所以它变成$sailings.Arrivals.PDH083.More 打破了我设置的路径。
我的代码版本:
$Sailings = @{
'Arrivals' = @{
'PDH083' = @{
'GoingTo' = 'Port1'
'Scheduled' = '09:05'
'Expected' = '10:11'
'Status' = 'Delayed'
}
}
'Departures' = @{
'PDH083' = @{
'ArrivingFrom' = 'Port1'
'Scheduled' = '09:05'
'Expected' = '09:05'
'Status' = 'OnTime'
'Other' = @{'Data' = 'Test'}
}
}
}
$Flights = @{
'Arrivals' = @{
'PDH083' = @{
'GoingTo' = 'Port'
'Scheduled' = '09:05'
'Expected' = '10:20'
'Status' = 'Delayed'
}
}
'Departures' = @{
'PDH083' = @{
'ArrivingFrom' = 'Port11'
'Scheduled' = '09:05'
'Expected' = '09:05'
'Status' = 'NotOnTime'
'Other' = @{'Data' = 'Test_Diff'}
}
}
}
function Compare-Hashtable {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Hashtable]$Left,
[Parameter(Mandatory = $true)]
[Hashtable]$Right,
[string] $path,
[boolean] $trackpath = $True
)
write-host "PAth received as: $path"
function New-Result($Key, $LValue, $Side, $RValue) {
New-Object -Type PSObject -Property @{
key = $Key
lvalue = $LValue
rvalue = $RValue
side = $Side
}
}
[Object[]]$Results = $Left.Keys | ForEach-Object {
if ($trackpath ) {
write-host "Working on Path: " $path + $_
}
if ($Left.ContainsKey($_) -and !$Right.ContainsKey($_)) {
write-host "Right key not matched. Report path as: $path"
New-Result $path $Left[$_] "<=" $Null
}
else {
if ($Left[$_] -is [hashtable] -and $Right[$_] -is [hashtable] ) {
if ($path -ne $null -or $path -ne "/") {
$path = $path + "/" + $_
write-host "Sending Path to function as: $path"
}
Compare-Hashtable $Left[$_] $Right[$_] $path
}
else {
$LValue, $RValue = $Left[$_], $Right[$_]
if ($LValue -ne $RValue) {
$path = $path + "/" + $_
write-host "Not a hash so must be a value at path:$path"
New-Result $path $LValue "!=" $RValue
}
else {
Write-Host "Before changing path: $path "
if (($path.Substring(0, $path.lastIndexOf('/'))).length >0) {
$path = $path.Substring(0, $path.lastIndexOf('/'))
Write-Host "After changing path: $path "
}
}
}
}
# if (($path.Substring(0, $path.lastIndexOf('/'))).length >0) {
# Tried to use this to stop error on substring being less than zero
# but clearly doesnt work when you add more levels to the hash
$path = $path.Substring(0, $path.lastIndexOf('/'))
# } else { $path = $path.Substring(0, $path.lastIndexOf('/')) }
}
$Results += $Right.Keys | ForEach-Object {
if (!$Left.ContainsKey($_) -and $Right.ContainsKey($_)) {
New-Result $_ $Null "=>" $Right[$_]
}
}
if ($Results -ne $null) { $Results }
}
cls
Compare-Hashtable $Sailings $Flights
outputs
key lvalue side rvalue
--- ------ ---- ------
/Arrivals/PDH083/Expected 10:11 != 10:20
/Arrivals/GoingTo Port1 != Port
/Departures/PDH083/ArrivingFrom Port1 != Port11
/Departures/PDH083/Status OnTime != NotOnTime
/Departures/PDH083/Other/Data Test != Test_Diff
【问题讨论】:
-
您还可以看到我的代码在 Arrivals/GoingTo 输出上丢失了 PDH083 密钥。所以,显然我以错误的方式解决了这个问题。
-
感谢@halfer 编辑问题。抱歉,我将在以后重新发布不必要的评论。至于我的英语水平,嗯,我尽力了,但我想这和我的编码能力一样好。
-
你的英语对我来说似乎很棒!
:-)是的,我们喜欢这里简洁的东西。
标签: powershell loops recursion hash