PowerShell中哈希表的并集和交集

9

PowerShell中的联合和交集?中,介绍了有关数组集合操作的酷炫一行代码。

我希望使用哈希表来实现这一点,并且已经找到了使用字典键集的解决方案。为了将其扩展到值,我使用for循环迭代键的交集并将值复制到新的结果哈希表中。但这看起来不够简洁。

进一步的研究显示,使用GetEnumerator也不够简洁。

我该如何用简洁而美观的一行代码替换臃肿的for循环或枚举器?

以下是源代码:

http://paste.ubuntu.com/13362425/

# import csv
$a = Import-Csv -Path A.csv -Delimiter ";" -Header "Keys","Values"
$b = Import-Csv -Path B.csv -Delimiter ";" -Header "Keys","Values"

# Make nice hashtables for further use
$AData = @{}
foreach($r in $a)
  { $AData[$r.Keys] = $r.Values }
$BData = @{}
foreach($r in $b)
  { $BData[$r.Keys] = $r.Values }

# Set difference to find missing entries
$MissingA = $AData.Keys | ?{-not ($BData.Keys -contains $_)}

# I don't know how to do set-operations on hashtables yet. So use keysets and copy data (lame!)
$MissingAData = @{}
foreach($k in $MissingA)
{
    $MissingAData[$k] = $AData[$k]
}

# Intersection
$Common = $AData.Keys | ?{$BData.Keys -contains $_}

你只对“值”感兴趣还是整个键值对都想要? - Adil Hindistan
整个键值对 - Bastl
1个回答

13

你可以使用与列表相同的技术,但要使用哈希表键,就像你在 OP 中指示的那样。

对于并集和交集,你有一个额外的问题。在两个哈希表之间共有的键中,你将保留哪个值?假设你总是保留第一个哈希表中的值。然后:

# need clone to prevent .NET exception of changing hash while iterating through it
$h1clone = $hash1.clone()

# intersection
$h1clone.keys | ? {$_ -notin $hash2.keys} | % {$hash1.remove($_)}

# difference: $hash1 - $hash2
$h1clone.keys | ? {$_ -in $hash2.keys}    | % {$hash1.remove($_)}

# union. Clone not needed because not iterating $hash1
$hash2.keys   | ? {$_ -notin $hash1.keys} | % {$hash1[$_] = $hash2[$_]}

或者你可以通过这种方式来避免克隆,并创建一个新的哈希表。

# intersection
$newHash = @{}; $hash1.keys | ? {$_ -in $hash2.keys} | % {$newHash[$_] = $hash1[$_]}

# difference: $hash1 - $hash2
$newHash = @{}; $hash1.keys | ? {$_ -notin $hash2.keys} | % {$newHash[$_] = $hash1[$_]}

工作得非常好,感谢关于交集中应保留哪个值的说明。 - Bastl
非常聪明,不错。 - CoffeeTableEspresso

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接