找出两个非常大的列表中的不同之处

dca*_*caz 1 powershell set-difference compareobject

我有两个列表,每个列表大约有 1k 人。我要做的就是找出两者之间剩下的是谁。

$BunchoEmail = Import-Csv C:\temp\Directory.csv | Select-Object primaryEmail -ExpandProperty primaryEmail

$GoogleUsers = gam print users fields suspended | ConvertFrom-Csv | Where-Object suspended -ne $true | Select-Object primaryEmail -ExpandProperty primaryEmail

$objects = @{
    ReferenceObject  = $GoogleUsers
    DifferenceObject = $BunchoEmail
}
Compare-Object @objects
Run Code Online (Sandbox Code Playgroud)

以上没有产生我想要的。

找到不同之处的最佳方法是什么?

mkl*_*nt0 5

Compare-Object 能够找到一个集合相对于另一个集合缺少哪些元素,反之亦然,或两者兼而有之。

但是,它可能很,并且考虑到您提到了大型列表,听起来您正在寻找一种性能良好的解决方案。

  • 但是,具有 1,000 个项目的集合在实践中可能不是问题

  • 因此像下面一些可足以获得在所有条目$BunchoEmail不在也在$GoogleUsers(替代=><=扭转逻辑):

    (Compare-Object -PassThru $BunchoEmail $GoogleUsers).
      Where({ $_.SideIndicator -eq '<=' })
    
    Run Code Online (Sandbox Code Playgroud)
  • 获取不在两个集合中的那些条目(对于任何一个集合都是唯一的)更容易:

    Compare-Object -PassThru $BunchoEmail $GoogleUsers
    
    Run Code Online (Sandbox Code Playgroud)

至于提高性能

将类型[System.Collections.Generic.HashSet`1]与 LINQ结合可以实现快速而简洁的解决方案:

笔记:

  • 的使用HashSet意味着结果的报告没有特定的顺序;要按排序顺序排列它们,请[System.Collections.Generic.SortedSet[string]]改用。(从 .NET 6 开始,没有用于维护插入顺序的内置类型)。

  • 下面的解决方案是真正的集合操作,即它们报告了明显的差异,不像Compare-Object。例如,如果唯一的电子邮件在一个集合中foo@example.org出现两次,下面的解决方案只报告一次,而Compare-Object报告两个实例。

  • 与 不同Compare-ObjectHashSetSortedSet类型默认区分大小写;您可以将相等比较器传递给不区分大小写行为的构造函数,使用System.StringComparer; 例如:

    [System.Collections.Generic.HashSet[string]]::new(
      [string[]] ('foo', 'FOO'),
      [System.StringComparer]::InvariantCultureIgnoreCase
    )
    
    Run Code Online (Sandbox Code Playgroud)

要获取所有$BunchoEmail不在 中的条目$GoogleUsers,请使用[System.Linq.Enumerable]::Except()(反转逆解的操作数):

[Linq.Enumerable]::Except(
  [System.Collections.Generic.HashSet[string]] $BunchoEmail,
  [System.Collections.Generic.HashSet[string]] $GoogleUsers
)
Run Code Online (Sandbox Code Playgroud)

注意:您也可以使用散列集的.ExceptWith()方法,但这需要将散列集之一存储在辅助变量中,然后就地更新- 类似于.SymmetricExceptWith()下面的解决方案。

使用散列集的方法获取不在两个集合中的那些条目(对于任何一个集合都是唯一的,称为集合项中的对称差异)需要更多的努力.SymmetricExceptWith()

# Load one of the collections into an auxiliary hash set.
$auxHashSet = [System.Collections.Generic.HashSet[string]] $BunchoEmail

# Determine the symmetric difference between the two sets, which
# updates the calling set in place.
$auxHashSet.SymmetricExceptWith(
  [System.Collections.Generic.HashSet[string]] $GoogleUsers
)

# Output the result
$auxHashSet
Run Code Online (Sandbox Code Playgroud)