簡體   English   中英

在兩個PowerShell陣列中查找常見項

[英]Find common items in two PowerShell arrays

我知道已經有一些堆棧溢出問題,但我已經嘗試了很多解決方案並繼續得到相同的錯誤。 問題是這樣的:

我有2個數組(每個索引代表一個文件夾)

$originDirsArr = @(2, 257, 256, 3, 4, 10)
$tempDirArr = @(2, 257, 256, 3, 4)

我想再次比較$ arr2 $ arr1,如果$ arr1中有東西不在$ arr2中,則刪除它。 即,在這種情況下,$ arr2中的10個DNE,因此該文件夾應該被刪除。

這是我嘗試過的:

$c = Compare-Object -ReferenceObject ($originDirsArr) `
 -DifferenceObject ($tempDirArr) -Passthru
$c

也:

while ($t -lt $originDirsArr.length){
$originDirsArr[$t]
    if ( $tempDirArr -notContain $originDirsArr[$t]){
        "$_ does not exist in original and needs to be deleted"
    }else{
        "$_ does still exist in the temp"
    }
    $t++
}

最后:

Compare-Object $originDirsArr $tempDirArr | ForEach-Object { $_.InputObject }

每次我不斷得到某種錯誤,無論是ReferenceObject還是DifferenceObject都是null。 我知道它不是null因為我可以打印出內容,即使在那個例子中在t上編入索引,我仍然有內容。

在先進的感謝,任何幫助將不勝感激!

我對compare-object也有一點厭惡。 由於這些是簡單的數組,因此只需一個foreach循環和-notcontains

$originDirsArr = @(2, 257, 256, 3, 4, 10)
$tempDirArr = @(2, 257, 256, 3, 4)

foreach ($item in $originDirsArr) {
    if ($tempDirArr -notcontains $item) {
        Write-Output "Do something with $item";
    }
}

使用HashSet泛型集合 它需要.NET 3.5。 它有一個IntersectWith方法,它將修改集合,使其僅包含兩個集合中的項目(例如AND兩個集合):

$originDirsSet = New-Object 'Collections.Generic.HashSet[int]' ,@(2, 257, 256, 3, 4, 10)
$tempDirSet = @(2, 257, 256, 3, 4)
$originDirsSet.IntersectWith( $tempDirSet )
# $originalDirsSet now contains 2, 257, 256, 3, 4

它有其他基於集合的方法:

  • ExceptWith :從當前HashSet<T>對象中刪除指定集合中的所有元素。
  • SymmetricExceptWith :修改當前的HashSet<T>對象,使其僅包含該對象或指定集合中存在的元素,但不包含兩者(即,這就像對集合進行XOR )。
  • UnionWith :修改當前的HashSet<T>對象以包含其自身,指定集合或兩者中存在的所有元素(即,這就像對集合進行OR )。

這是一個1班輪這樣做。 它與接受的答案相同,因為它遍歷一個數組,然后使用-contains將該項與另一個數組進行比較。 這里的區別是我們使用where-object函數並返回結果集,而不是在for循環中使用if語句。 還使用PowerShell的簡寫符號來減少代碼量(無論是好的還是“壞的”都是值得商榷的)。

#setting up
$originDirsArr = @(2, 257, 256, 3, 4, 10)
$tempDirArr = @(2, 257, 256, 229, 3, 4)

#get items in 1 array but not the other 
[int[]]$leftOnly = $originDirsArr | ?{$tempDirArr -notcontains $_}

#or an intersect operation
[int[]]$intersect = $originDirsArr | ?{$tempDirArr -contains $_}

#display results
"Left Only"; $leftOnly 
"Intersect"; $intersect 

或者,如果這是您經常做的事情,為這種類型的操作提供方便的功能可能是有用的:

set-alias ?@@ Apply-ArrayOperation #http://stackoverflow.com/a/29758367/361842
function Apply-ArrayOperation {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory, Position=0)]
        [object[]]$Left
        ,
        [Parameter(Mandatory,ParameterSetName='exclude', Position=1)]
        [switch]$exclude
        ,
        [Parameter(Mandatory,ParameterSetName='intersect', Position=1)]
        [switch]$intersect
        ,
        [Parameter(Mandatory,ParameterSetName='outersect', Position=1)] #not sure what the correct term for this is
        [switch]$outersect
        ,
        [Parameter(Mandatory,ParameterSetName='union', Position=1)] #not sure what the correct term for this is
        [switch]$union
        ,
        [Parameter(Mandatory,ParameterSetName='unionAll', Position=1)] #not sure what the correct term for this is
        [switch]$unionAll
        ,
        [Parameter(Mandatory, Position=2)]
        [object[]]$Right
    )
    begin {
        #doing this way so we can use a switch staement below, whilst having [switch] syntax for the function's caller 
        [int]$action = 1*$exclude.IsPresent + 2*$intersect.IsPresent + 3*$outersect.IsPresent + 4*$union.IsPresent + 5*$unionAll.IsPresent
    }
    process {
        switch($action) {
            1 {$Left | ?{$Right -notcontains $_}} 
            2 {$Left | ?{$Right -contains $_} }
            3 {@($Left | ?{$Right -notcontains $_}) + @($Right | ?{$Left -notcontains $_})}       
            4 {@($Left) + @($Right) | select -Unique}       
            5 {@($Left) + @($Right)}       
        }
    }
}

$array1 = @(1,3,5,7,9)
$array2 = @(2,3,4,5,6,7)

"Array 1"; $array1
"Array 1"; $array2

"Array 1 Exclude Array 2";   ?@@ $array1 -exclude $array2 
"Array 1 Intersect Array 2"; ?@@ $array1 -intersect $array2
"Array 1 Outersect Array 2"; ?@@ $array1 -outersect $array2
"Array 1 Union Array 2";     ?@@ $array1 -union $array2
"Array 1 UnionAll Array 2";  ?@@ $array1 -unionall $array2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM