我正在尝试找到返回存储在数组中的哈希表的最佳方法,匹配另一个与数组分开的哈希表的所有属性。
例如,我有以下数组和哈希表变量:
$myarr = @(
@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E"},
@{"first" = "M";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E";"sixth"="F"},
@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "Z"})
$crit = @{"first"="A";"third"="C"}
我需要一种方法来返回存储在数组中的每个整个哈希表,其中来自$crit
的所有属性都匹配。在此示例中,我希望看到$myarr[0]
和$myarr[2]
返回。
我可以通过逐个遍历$crit
的属性,并将它们与数组中的每个哈希表进行比较来实现这一点,但是我想知道是否有更好的方法来比较哈希我无法弄清楚的表,类似于带有数组的Compare-Object
。
ForEach ($hash in $myarr) {
$match = $true
ForEach ($key in $crit.Keys) {If ($hash.$key -ne $crit.$key) {$match = $false;Break}}
If ($match) {$hash}}
最终目标是与最少的内存使用量进行比较,因为真实世界的应用程序将比较数十万个这样的数组,其中包含数百个哈希表,它们都有100多个属性。显然,任何帮助都朝着正确的方向前进,我的目标是尽可能简化这种比较。
答案 0 :(得分:0)
设置基本功能,根据一个哈希表测试您的条件,然后使用Where-Object
过滤哈希表数组。
对于第一部分,我们可以做这样的事情
function Compare-HashtableSubset
{
param(
[Parameter(Mandatory,Position=0)]
[hashtable]$HashTable,
[Parameter(Mandatory,Position=1)]
[hashtable]$SubTable
)
foreach($entry in $SubTable.GetEnumerator()) {
if((-not $HashTable.ContainsKey($entry.Key)) -or $HashTable[$entry.Key] -ne $entry.Value){
# missing key or value mismatch, we're done here
return $false
}
}
# made it to the end, must be good
return $true
}
现在我们可以比较两个哈希表,让我们使用它!
PS C:\> $filteredArray = $myarr |Where-Object { Compare-HashtableSubset $_ $crit }
PS C:\> $filteredArray.Count
2
答案 1 :(得分:0)
不知道这是否有帮助,但您可以针对测试集运行它,看看它是否比蛮力迭代更好地扩展:
$myarr = @(
@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E"},
@{"first" = "M";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E";"sixth"="F"},
@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "Z"})
$crit = @{"first"="A";"third"="C"}
$match1 = '*"first": "A"*'
$match2 = '*"third": "C"*'
($myarr |% {$_ | convertto-json}) -like $match1 -like $match2 | convertfrom-json
您可能需要也可能不需要最后一次转换来自-json。如果JSON的结果是可接受的,它应该在没有它的情况下运行得更快。它将使用比蛮力迭代更多的内存,但应该一次完成整个数组,而不是一次执行一个哈希表。
答案 2 :(得分:0)
首先将哈希值转换为对象。我已经包含了两个可能的选项
$myarr = @(
@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E"},
@{"first" = "M";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E";"sixth"="F"},
@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "Z"}
)|ForEach-Object {New-Object -TypeName psobject -Property $_}
# or
$myarr = @(
[pscustomobject]@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E"},
[pscustomobject]@{"first" = "M";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E";"sixth"="F"},
[pscustomobject]@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "Z"}
)
然后开始过滤集合
$result
Where-Object
过滤此条件$result
代码看起来像这样
$crit = @{"first"="A";"third"="C"}
$result=$myarr
$crit.GetEnumerator()|ForEach-Object {
$result=$result|Where-Object -Property $_.Name -EQ $_.Value
}
$result
输出
first : A
second : B
third : C
fourth : D
fifth : E
first : A
second : B
third : C
fourth : D
fifth : Z