Subtraction arrays (Powershell)

There are two $A and $B arrays . I need to get a third $C array, which would be consisted of all the elements of the first array, which are absent in the second. I.e. $A = $B + $C. Of course, the length of $B array plus length of $C array is equal to the length of $A array.

$A = 'a', 'b', 'c', 'a', 'a' 

$B = 'b', 'a', 'a' 

# This is an array that is consisted of elements of the first array that are not in the second array.

$C = 'a', 'c' 

By itself, the next action does not work, so it will delete all matches:

# Not suitable

$A | Where-Object { $B -notcontains $_ }

---
c

This solution should work. However, as I understand it, in Powershell there is no operation to remove an element from an array. That is, there is no such operation: { Remove $j element from $A array }

ForEach ($i in $B) { 

    ForEach ($j in $A) { 

        if ($i -eq $j) { { Remove $j value from $A array }; break }
    }
}

And apparently in the process of learning Powershell, I've missed something. I will ask you if there's any operation to remove array element. And how can I get my desired $C array?

Upvotes: 2

Views: 1859

Answers (2)

PMental
PMental

Reputation: 1179

Arrays are fixed size, so you can't remove items from them (best you can do is null them) nor add objects. Methods like the += operation that seems to add to an array actually recreates an entirely new array to add values which is slow, this and more is covered quite well in the "about_Arrays" documentation which is worth a read.

For a versatile type of list that can be used for all kinds of things look into the "Generic List" type, that one has both Add and Remove methods (and more) and is quite useful at times.

Docs: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1

PowerShell Example:

$List = New-Object 'System.Collections.Generic.List[System.Object]'
$List.AddRange(('Test','Test2','Test3'))
$List.Remove('Test2')

Or an example with more complex objects:

$List = New-Object 'System.Collections.Generic.List[System.Object]'
$List.AddRange((Get-Process))
$List.Remove($($List.Where({$_.ProcessName -eq 'Calculator'})))

The "System.Object" part could also be more narrow and specific like [String] or [Int].

Upvotes: 2

hcm
hcm

Reputation: 1020

You're looking for compare-object: link

$A = 'a', 'b', 'c', 'a', 'a' 
$B = 'b', 'a', 'a' 

Compare-Object -ReferenceObject $a -DifferenceObject $b

Output:

InputObject SideIndicator
----------- -------------
c           <=           
a           <=           

Upvotes: 3

Related Questions