使用 PowerShell,我有 14 個字串陣列。一些陣列是空的。如何獲得這些陣列(不包括空陣列)的交集(所有陣列中存在的所有元素)?我試圖避免一次比較兩個陣列。
有些陣列是空的,所以我不想在我的比較中包括這些。關于我將如何解決這個問題的任何想法?謝謝你。
$a = @('hjiejnfnfsd','test','huiwe','test2')
$b = @('test','jnfijweofnew','test2')
$c = @('njwifqbfiwej','test','jnfijweofnew','test2')
$d = @('bhfeukefwgu','test','dasdwdv','test2','hfuweihfei')
$e = @('test','ddwadfedgnh','test2')
$f = @('test','test2')
$g = @('test','bjiewbnefw','test2')
$h = @('uie287278hfjf','test','huiwhiwe','test2')
$i = @()
$j = @()
$k = @('jireohngi','test','gu7y8732hbj','test2')
$l = @()
$m = @('test','test2')
$n = @('test','test2')
我嘗試解決這個問題(盡管它不檢查空陣列):
$overlap = Compare-Object $a $b -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $c -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $d -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $e -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $f -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $g -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $h -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $i -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $j -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $k -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $l -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $m -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $n -PassThru -IncludeEqual -ExcludeDifferent
我想要的結果是 test 和 test2 出現在 $overlap 中。此解決方案不起作用,因為它不檢查它正在比較的陣列是否為空。
uj5u.com熱心網友回復:
注意:以下假設沒有單個陣列多次包含相同的字串(需要做更多的作業來解決這個問題)。
$a = @('hjiejnfnfsd','test','huiwe','test2')
$b = @('test','jnfijweofnew','test2')
$c = @('njwifqbfiwej','test','jnfijweofnew','test2')
$d = @('bhfeukefwgu','test','dasdwdv','test2','hfuweihfei')
$e = @('test','ddwadfedgnh','test2')
$f = @('test','test2')
$g = @('test','bjiewbnefw','test2')
$h = @('uie287278hfjf','test','huiwhiwe','test2')
$i = @()
$j = @()
$k = @('jireohngi','test','gu7y8732hbj','test2')
$l = @()
$m = @('test','test2')
$n = @('test','test2')
$allArrays = $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n
# Initialize a hashtable in which we'll keep
# track of unique strings and how often they occur.
$ht = @{}
# Loop over all arrays.
$nonEmptyArrayCount = 0
foreach ($arr in $allArrays) {
# Loop over each non-empty array's elements.
if ($arr.Count -gt 0) {
$nonEmptyArrayCount
foreach ($el in $arr) {
# Add each string and increment its occurrence count.
$ht[$el] = 1
}
}
}
# Output all strings that occurred in every non-empty array
$ht.GetEnumerator() |
Where-Object Value -eq $nonEmptyArrayCount |
ForEach-Object Key
以上輸出所有非空輸入陣列中存在的那些字串:
test2
test
uj5u.com熱心網友回復:
你很近。從比較中排除空陣列是必不可少的,因為空陣列和任何其他陣列的交集是一個空陣列,并且一旦$overlap包含一個空陣列,無論后續陣列包含什么,它將成為最終結果。
這是帶有非空檢查并使用回圈重寫的代碼...
$a = @('hjiejnfnfsd', 'test', 'huiwe', 'test2')
$b = @('test', 'jnfijweofnew', 'test2')
$c = @('njwifqbfiwej', 'test', 'jnfijweofnew', 'test2')
$d = @('bhfeukefwgu', 'test', 'dasdwdv', 'test2', 'hfuweihfei')
$e = @('test', 'ddwadfedgnh', 'test2')
$f = @('test', 'test2')
$g = @('test', 'bjiewbnefw', 'test2')
$h = @('uie287278hfjf', 'test', 'huiwhiwe', 'test2')
$i = @()
$j = @()
$k = @('jireohngi', 'test', 'gu7y8732hbj', 'test2')
$l = @()
$m = @('test', 'test2')
$n = @('test', 'test2')
# Create an array of arrays $a through $n
$arrays = @(
# 'a'..'n' doesn't work in Windows PowerShell
# Define both ends of the range...
# 'a' → [String]
# 'a'[0] → [Char]
# [Int32] 'a'[0] → 97 (ASCII a)
# ...and cast each element back to a [Char]
[Char[]] ([Int32] 'a'[0]..[Int32] 'n'[0]) |
Get-Variable -ValueOnly
)
# Initialize $overlap to the first non-empty array
for ($initialOverlapIndex = 0; $initialOverlapIndex -lt $arrays.Length; $initialOverlapIndex )
{
if ($arrays[$initialOverlapIndex].Length -gt 0)
{
break;
}
}
<#
Alternative:
$initialOverlapIndex = [Array]::FindIndex(
$arrays,
[Predicate[Array]] { param($array) $array.Length -gt 0 }
)
#>
$overlap = $arrays[$initialOverlapIndex]
for ($comparisonIndex = $initialOverlapIndex 1; $comparisonIndex -lt $arrays.Length; $comparisonIndex )
# Alternative: foreach ($array in $arrays | Select-Object -Skip $initialOverlapIndex)
{
$array = $arrays[$comparisonIndex]
if ($array.Length -gt 0)
{
$overlap = Compare-Object $overlap $array -PassThru -IncludeEqual -ExcludeDifferent
}
}
$overlap
...輸出...
test
test2
uj5u.com熱心網友回復:
這是一個使用Hashset. A是一個只存盤唯一項并提供快速查找Hashset的集合,這使其成為交集計算的不錯選擇。它甚至有一個接受任何可列舉型別(例如陣列)作為引數的方法。該方法修改了原始方法,使其僅包含傳遞給該方法的引數和引數中包含的元素。IntersectWithHashsetHashset
# Test input
$a = @() # I changed this to empty array for demonstration purposes
$b = @('test','jnfijweofnew','test2')
$c = @('njwifqbfiwej','test','jnfijweofnew','test2')
$d = @('bhfeukefwgu','test','dasdwdv','test2','hfuweihfei')
$e = @('test','ddwadfedgnh','test2')
$f = @('test','test2')
$g = @('test','bjiewbnefw','test2')
$h = @('uie287278hfjf','test','huiwhiwe','test2')
$i = @()
$j = @()
$k = @('jireohngi','test','gu7y8732hbj','test2')
$l = @()
$m = @('test','test2')
$n = @('test','test2')
# Create a variable with a type-constraint
[Collections.Generic.Hashset[object]] $overlap = $null
# For each of the arrays...
($a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n).
Where{ $_.Count -gt 0 }. #... except the empty ones
ForEach{
# If the Hashset has not been initialized yet
if( $null -eq $overlap ) {
# Create the initial hashset from the first non-empty array.
$overlap = $_
}
else {
# Hashset is already initialized, calculate the intersection with next non-empty array.
$overlap.IntersectWith( $_ )
}
}
$overlap # Output
輸出:
test
test2
評論:
為了過濾掉空陣列(或者一般來說任何型別的集合),我們檢查它的
Count成員,它給出了元素的數量。.Foreach并且.Where是 PowerShell內在方法。這些可能比ForEach-ObjectandWhere-Object命令更快,尤其是在直接使用集合時(而不是另一個命令的輸出)。像往常一樣,自動變數$_表示集合的當前元素。這段使用管道命令的代碼在功能上是相同的:
[Collections.Generic.Hashset[object]] $overlap = $null $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n | Where-Object Count -gt 0 | ForEach-Object{ if( $null -eq $overlap ) { $overlap = $_ } else { $overlap.IntersectWith( $_ ) } }在操作員的左側
if( $null -eq $overlap )非常重要。如果它在右側,PowerShell 將與過濾元素進行元素比較,而不是檢查變數本身是否是(請參閱關于比較運算子)$null-eq$null$overlap$null在這一行中,
$overlap = $_PowerShell 自動將當前陣列轉換為 aHashset,因為我們使用before設定了型別約束并且可以轉換為(請參閱關于變數)。[Collections.Generic.Hashset[object]] $overlaparrayHashset默認情況下,a 的字串比較
Hashset區分大小寫。要使其不區分大小寫,請將每個字串轉換為小寫,如下所示:[Collections.Generic.Hashset[object]] $overlap = $null ($a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n). Where{ $_.Count -gt 0 }. ForEach{ if( $null -eq $overlap ) { $overlap = $_.ToLower() } else { $overlap.IntersectWith( $_.ToLower() ) } }這使用成員訪問列舉來呼叫
String.ToLower()輸入陣列的每個元素的方法。對于第一個變體,在and之前 插入換行符并不是必需的,但可以提高代碼的可讀性(請注意,您不能在and之前插入換行符,因為這會使 PowerShell 決議器感到困惑)。
WhereForEach.Where.ForEach
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/490687.html
