我有一个 powershell 脚本,它使用 Compare-Object
来比较/比较 MD5 校验和的列表……我怎样才能加快速度?它已经运行了几个小时!
$diffmd5 =
(Compare-Object -ReferenceObject $localmd5 -DifferenceObject $remotefilehash |
Where-Object { ($_.SideIndicator -eq '=>') } |
Select-Object -ExpandProperty InputObject)
最佳答案
Compare-Object
方便,但确实慢;完全避免流水线对于最大化性能也很重要。
我建议使用 [System.Collections.Generic.HashSet[T]
实例,它支持在一组无序[1] 值中进行高性能查找:[2]
# Two sample arrays
$localmd5 = 'Foo1', 'Bar1', 'Baz1'
$remotefilehash = 'foo1', 'bar1', 'bar2', 'baz1', 'more'
# Create a hash set from the local hashes.
# Make lookups case-*insensitive*.
# Note: Strongly typing the input array ([string[]]) is a must.
$localHashSet = [System.Collections.Generic.HashSet[string]]::new(
[string[]] $localmd5,
[System.StringComparer]::OrdinalIgnoreCase
)
# Loop over all remote hashes to find those not among the local hashes.
$remotefilehash.Where({ -not $localHashSet.Contains($_) })
以上生成集合 'bar2', 'more'
。
请注意,如果大小写敏感 查找就足够了,这是默认设置(对于字符串元素),一个简单的cast 就足以构造哈希集:
$localHashSet = [System.Collections.Generic.HashSet[string]] $localmd5
注意:您后来的反馈指出,$remotefilehash
是一个哈希表(类似)键值对集合,而不是单纯的文件哈希集合strings,其中 keys 存储哈希字符串。在那种情况下:
仅查找不同的散列 strings(注意
.Keys
属性访问以获取键值数组):$remotefilehash.Keys.Where({ -not $localHashSet.Contains($_) })
找到那些键不在哈希集中的键值对(注意
.GetEnumerator()
调用以枚举所有条目(key-值对)):$remotefilehash.GetEnumerator().Where({ -not $localHashSet.Contains($_.Key) })
或者,如果输入集合 (a) 具有相同的大小并且 (b) 具有对应的元素(即,一个集合中的元素 1 应与另一个集合中的元素 1 进行比较,依此类推),使用 Compare-Object
与-SyncWindow 0
,如js2010's helpful answer所示, 随后的 .SideIndicator
过滤可能是一个选项;为了加快操作速度,应该使用 -PassThru
开关,它放弃将不同的对象包装在 [pscustomobject]
实例中(.SideIndicator
然后将属性作为 NoteProperty
成员直接添加到不同的对象中)。
[1] 有一个相关的类型用于维护已排序值,System.Collections.Generic.SortedSet[T]
,但是 - 从 .NET 6 开始 - 没有用于按输入顺序维护值的内置类型,但您可以通过以下方式创建自己的类型源自 [System.Collections.ObjectModel.KeyedCollection[TKey, TItem]]
[2] 请注意,哈希集——与哈希表不同——没有与其条目关联的值。哈希集是“所有键”,如果您愿意的话 - 它所支持的只是测试键 == 值的存在。
关于powershell - 如何最好地加快 powershell 处理时间(比较对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67662779/