我知道已经有一些堆栈溢出问题,但我已经尝试了很多解决方案并且不断出现同样的错误。问题是:
我有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上编入索引,我仍然有内容。
先谢谢,非常感谢任何帮助!
答案 0 :(得分:5)
我对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";
}
}
答案 1 :(得分:2)
使用HashSet generic collection。它需要.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
集合。)< / LI>
答案 2 :(得分:2)
这是一个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