[英]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.