【发布时间】:2022-01-27 02:18:53
【问题描述】:
假设我有几个 CSV 文件,我需要检查特定列并查找存在于一个文件中但不存在于其他任何文件中的值。由于我想使用Compare-Object 并可能保留所有列,而不仅仅是包含我正在检查的值的列,所以我在想出最好的方法时遇到了一些麻烦。
所以我确实有几个 CSV 文件,它们都有一个 Service Code 列,我正在尝试为每个 Service Code 创建一个仅出现在一个文件中的列表。所以我会有“仅在 CSV1 中的服务代码”、“仅在 CSV2 中的服务代码”等。
基于一些测试和semi-related question,我想出了一个可行的解决方案,但是对于所有的嵌套和For 循环,我想知道是否有更优雅的方法。
这是我所拥有的:
$files = Get-ChildItem -LiteralPath "C:\temp\ItemCompare" -Include "*.csv"
$HashList = [System.Collections.Generic.List[System.Collections.Generic.HashSet[String]]]::New()
For ($i = 0; $i -lt $files.Count; $i++){
$TempHashSet = [System.Collections.Generic.HashSet[String]]::New([String[]](Import-Csv $files[$i])."Service Code")
$HashList.Add($TempHashSet)
}
$FinalHashList = [System.Collections.Generic.List[System.Collections.Generic.HashSet[String]]]::New()
For ($i = 0; $i -lt $HashList.Count; $i++){
$UniqueHS = [System.Collections.Generic.HashSet[String]]::New($HashList[$i])
For ($j = 0; $j -lt $HashList.Count; $j++){
#Skip the check when the HashSet would be compared to itself
If ($j -eq $i){Continue}
$UniqueHS.ExceptWith($HashList[$j])
}
$FinalHashList.Add($UniqueHS)
}
使用这么多不同的 .NET 引用对我来说似乎有点混乱,我知道我可以用一个标签说using namespace System.Collections.Generic 让它更干净,但我想知道是否有办法让它工作使用Compare-Object 这是我的第一次尝试,甚至只是过滤每个文件的更简单/更有效的方法。
【问题讨论】:
-
您拥有的 CSV 中的哪一个是“参考 CSV”,或者您是否希望比较所有这些 CSV 并找到唯一值?另外,您是在寻找效率还是优雅,这是个人意见,但
hashshet比Compare-Object更优雅和高效(再次,个人喜好) -
一个文件中是否可以有重复的服务代码?
-
在 99.9% 的情况下,单个文件中很可能不会有重复项。 @SantiagoSquarzon - 我正在尝试将每个人与其他人进行比较。因此,如果我使用
Compare-Object,它会变得非常嵌套,并且可能不符合任何定义的优雅 -
我没有看到您的
hashset上有[System.StringComparer]::OrdinalIgnoreCase,这是您应该担心的事情吗? (除了区分大小写不同之外,还有可能具有相同值的代码) -
我可以将大小写逻辑作为安全检查,但所有内容都应在源文件中转换为大写,所以这不是一个大问题。
HashSet过程还不错,而且相当快,但现在我开始认为我可能会导出结果,包括“服务代码”以外的列,所以在我将所有内容转换为HashTables和PSCustomObjects 作为键,我想我会检查是否有更好的方法,因为我无法让Compare-Object开心
标签: powershell