不区分大小写[Linq.Enumerable]::SequenceEqual()
例如,我一直[Linq.Enumerable]::SequenceEqual()用来比较两个数组中项目的顺序
$validOrder = @('one', 'two', 'three')
$provided = @('one', 'two', 'three')
[Linq.Enumerable]::SequenceEqual($validOrder, $provided)
这有效,但现在我意识到我想独立解决大写错误,所以我想以不区分大小写的方式测试订单。我发现这记录了一个不同的方法签名,IEqualityComparer<T>作为第三个值。这确实看起来是正确的方向,但我还没有找到任何可以帮助我在 powershell 中实现它的东西。我尝试只使用 'OrdinalIgnoreCase' 作为最后一个参数,[String].FindIndex()正如另一个线程中指出的那样。但可惜不是这里。我还发现这实际上为不同的对象类型制作了一个自定义比较器,但似乎我刚刚手动实现了我真正想要的东西,我不确定使用的价值是什么[Linq.Enumerable]::SequenceEqual(),我可以将我的数组传递给我的类方法并直接在那里完成工作。
如果 (-not (Compare-Object -SyncWindow 0 $validOrder $provided)) { $result = 'ordered' } else { $result = 'disordered' } 并且它已经不区分大小写,我也使这种方法有效。但它也更慢,我可能有很多这样的测试要做,所以速度会有好处。
最后,我看到这似乎有效,并且非常简单,不区分大小写(如果我愿意)并且看起来很快。数组中的项目总数总是很小,不同数组的重复次数是性能问题。
$result = ($provided -join ' ') -eq ($validOrder -join ' ')
那么,最后一个选项是否可行,或者我是否遗漏了一些明显反对它的内容?
另外,我觉得我还会IEqualityComparer<T>遇到其他有用的论点,因此知道如何去做会很有用。假设我读对了,并IEqualityComparer<T>提供了一种不同形式的比较机制,而不仅仅是滚动我自己的比较。
回答
我尝试只使用“OrdinalIgnoreCase”作为最后一个参数,...
你离我很近:
$lower = 'a b c'.Split()
$upper = 'A B C'.Split()
$ignoreCaseComparer = [System.StringComparer]::OrdinalIgnoreCase
[Linq.Enumerable]::SequenceEqual($lower, $upper, $ignoreCaseComparer)
该StringComparer班-不要与混淆StringComparison枚举类型-工具IEqualityComparer<string>,所以满足类型约束。
请注意,上述方法调用仅有效,因为我曾经String.Split()创建方法参数,并Split()显式返回[string[]]- 对于大多数其他类似数组的表达式,您可能会发现自己需要显式键入输入参数,以便 PowerShell 传递正确的类型参数:
# This will fail - type of `@()` is [object[]],
# and `SequenceEquals<object>()` doesn't accept stringcomparer
$lower = @(-split 'a b c')
$upper = @(-split 'A B C')
$ignoreCaseComparer = [System.StringComparer]::OrdinalIgnoreCase
[Linq.Enumerable]::SequenceEqual($lower, $upper, $ignoreCaseComparer)
# This will succeed thanks to the cast(s) to [string[]] at the call site
$lower = @(-split 'a b c')
$upper = @(-split 'A B C')
$ignoreCaseComparer = [System.StringComparer]::OrdinalIgnoreCase
[Linq.Enumerable]::SequenceEqual([string[]]$lower, [string[]]$upper, $ignoreCaseComparer)