PowerShell中的联盟和交集?

时间:2011-12-22 20:12:03

标签: arrays powershell

我有一系列具有以下结构的对象:

structure Disk
{
  int UID;
  String Computer;
}

计算机可能有一堆共享磁盘,并且可以在计算机之间共享磁盘。

我想找出所有计算机常用的所有磁盘。例如,我有计算机A,B和C;磁盘1,2和3。 磁盘阵列为{1,A},{1,B},{2,A},{2,B},{2,C},{3,A}。 我想要的结果应该是磁盘2,因为它出现在A,B和C上。

有没有一种有效的方法来实现这一目标?

有多个foreach循环,它是可以实现的,但绝对我想要一个更好的方法。我正在考虑像交集这样的操作,但是在PowerShell中没有找到它。

4 个答案:

答案 0 :(得分:71)

假设$arr是数组,您可以这样做:

$computers = $arr | select -expand computer -unique
$arr | group uid | ?{$_.count -eq $computers.count} | select name

一般来说,我会在Powershell中接近联合和交集:

$a = (1,2,3,4)
$b = (1,3,4,5)
$a + $b | select -uniq    #union
$a | ?{$b -contains $_}   #intersection

但是对于你所问的问题,上述解决方案效果很好,而不是关于术语标准定义中的并集和交集。

更新

我写了pslinq,它提供了Union-ListIntersect-List,有助于实现与Powershell的集合和交集。

答案 1 :(得分:12)

您也可以

$a = (1,2,3,4)
$b = (1,3,4,5)
Compare-Object $a $b -PassThru -IncludeEqual                   # union
Compare-Object $a $b -PassThru -IncludeEqual -ExcludeDifferent # intersection

如果$a为空,则无效。

答案 2 :(得分:10)

对于集合减法(a - b):

$a | ?{-not ($b -contains $_)}

答案 3 :(得分:6)

虽然这在最早的版本中不起作用,但在更新的版本中,您可以直接调用.NET LINQ扩展函数,例如。

[system.linq.enumerable]::union([object[]](1,2,3),[object[]](2,3,4))

(如果没有强制转换为某种可枚举的类型,PowerShell会抛出一个"找不到重载"错误。)

这绝对适用于PowerShell V4和V5,绝对不会在V2中使用。我没有V3的系统。