1

I have these arrays, I want to list unique values. If a value in $arr2 is in $arr1 I want to list that out but only ONE time. If a value in $arr2 is NOT in $arr1 I want to list that out as well. I would like to also add the values in $arr2 that are not contained in $arr1 to a seperate array. This is written in powershell but if you have a solution/tips in any other language that is perfectly fine with me I will rewrite to powershell.

$arr1 = @(1,1,1,2,2,3,4,4,5,7) 
$arr2= @(1,2,3,4,5,6,7) 

for ($i = 0; $i -lt $arr2.length; $i++){
    for( $j = $i+1; $j -lt $arr1.length; $j++ ){ 
        if($arr2[$i] -eq $arr1[$j]){
            Write-Host $arr2[$i]
        }
}
}
sorifiend
  • 5,927
  • 1
  • 28
  • 45
robertuxo
  • 35
  • 8
  • 1
    take a look at the `hashset` object type. >>> Set (data structure) in PowerShell - Stack Overflow — https://stackoverflow.com/questions/29126555/set-data-structure-in-powershell – Lee_Dailey Oct 20 '21 at 01:03
  • Does this answer your question? [Comparing two arrays & get the values which are not common](https://stackoverflow.com/questions/6368386/comparing-two-arrays-get-the-values-which-are-not-common): `($a | Where {$b -NotContains $_}) + ($b | Where {$a -NotContains $_})` – iRon Oct 20 '21 at 07:32

2 Answers2

1

You can use something like this to create an object which can be used for your need, however it will require further code from your side (i.e.: filtering) to get the results you're looking for.

$arr1 = @(1,1,1,2,2,3,4,4,5,7)
$arr2 = @(1,2,3,4,5,6,7)
$result = [System.Collections.Generic.List[pscustomobject]]::new()

foreach($i in $arr1 + $arr2)
{
    if($i -in $result.Value)
    {
        continue
    }

    $z = [ordered]@{
        Value = $i
        Array1 = $false
        Array2 = $false
    }

    if($i -in $arr1)
    {
        $z.Array1 = $true
    }

    if($i -in $arr2)
    {
        $z.Array2 = $true
    }

    $result.Add([pscustomobject]$z)
}

$valuesOnBothArrays, $valuesOnOneArray = $result.Where({
    $_.Array1 -eq $true -and $_.Array2 -eq $true}, 'Split'
)
  • $valuesOnBothArrays will result in:
Value Array1 Array2
----- ------ ------
    1   True   True
    2   True   True
    3   True   True
    4   True   True
    5   True   True
    7   True   True
  • $valuesOnOneArray will result in:
Value Array1 Array2
----- ------ ------
    6  False   True
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
1

I suggest using the Compare-Object cmdlet in combination with the .Where() array method:

$arr1 = 1,1,1,2,2,3,4,4,5,7
$arr2 = 1,2,3,4,5,6,7

$inBoth, $uniqueRight = 
  (Compare-Object -PassThru -IncludeEqual `
    ($arr1 | Select-Object -Unique) ($arr2 | Select-Object -Unique)).
      Where({ $_.SideIndicator -in '==', '=>' }).
      Where({ $_.SideIndicator -eq '==' }, 'Split')

"-- in both:"
$inBoth

"-- unique to arr2"
$uniqueRight

Note: Thanks to using Select-Object -Unique on the input arrays so as to only operate on distinct elements, the use of -PassThru with Compare-Object works as expected and passes the integers of interest through directly, rather than as properties of wrapper objects. The caveat is that with [int] array elements specifically, because PowerShell caches values up to 100, having duplicates in either collection would malfunction obscurely. The reason is that -PassThru decorates the pass-through elements with an ETS .SideIndicator property, which affects all uses of a given integer between 0 and 100, so that the .SideIndicator property value of a later duplicate would overwrite the original value - see this answer for more information.

Note:

  • If you know that the distinct elements of $arr1 are only ever a subset of the ones in $arr2, i.e. that $arr1 contains no unique elements, you can eliminate the intermediate .Where({ $_.SideIndicator -in '==', '=>' }) call.

  • Unfortunately, as of PowerShell 7.2, the implementation of Select-Object -Unique is quite inefficient - see GitHub issue #11221. If the input arrays were sorted, Get-Unique would be a faster alternative.

The above yields:

-- in both (distinct):
1
2
3
4
5
7
-- unique to arr2
6
mklement0
  • 382,024
  • 64
  • 607
  • 775