Home > Blockchain >  Compare 2 arrays with powershell
Compare 2 arrays with powershell

Time:09-01

I have 2 Arrays $UsersGroup and $UsersActive, i need to find where in $UsersActive i have a line with SamAccountName and the ObjectGUID .

$UsersGroup =

SamAccountName ObjectGUID
-------------- ----------
XXXX00XX       0031e949-9120-4df1-bddb-98067a141448
XXXX01XX       0031e949-9120-4df1-bdgb-99067a141448
XXXX02XX       0031e949-9120-4df1-bdab-97067a141448

and without headers

$UsersActive =

fcb483fa146b
fcb515739a2f
fcb82f1ef74c
fcc5ee8b8722
fcd3f1f471c2
fceb26a598a3
fd0b14cecd0e
98067a141448

I need to have the match user from $UsersActive to $UserGroup.Object like that

$UsersGroup | ForEach-Object {if($_.ObjectGUID -contains $UsersActive) {$_}}

But i don't get the result like that :

XXXX00XX 0031e949-9120-4df1-bddb-98067a141448

Can some one help me , thanks !

CodePudding user response:

-contains is a collection containment operator, testing for the exact occurrence of the right-hand side argument in the left-hand side argument.

To test for the presence of a substring in a string, use the -like wildcard string comparison operator:

$UsersGroup | Where-Object {
    $guid = $_.ObjectGUID
    $UsersActive.Where({$guid -like "*$_*"}, 'First')
}

Each group entry will now be tested against every $UsersActive value until a match is found (causing Where-Object to pass the object through) or no match is found (causing Where-Object to filter out the object)

CodePudding user response:

To offer an alternative solution:

As Mathias states in his answer, the -contains operator and its operands-reversed counterpart, -in, only perform equality comparison of a single comparison value against the elements of a collection (array).

  • As an aside: Given that $_.ObjectGUID is the scalar (single object) and $UsersActive the collection (array) to search in, you would have needed to use -in, not -contains ($_.ObjectGUID -in $UsersActive)

Unfortunately, as of version 7.2.x PowerShell's pattern-matching operators, -like (with wildcard expressions) and -match (with regexes), do not support matching against multiple (an array of) patterns.

However, since you're looking to match a literal substring of each .ObjectGUID value, you can use -in if you extract that relevant substring first and use it as the comparison value:

# -> Object whose GUID is '0031e949-9120-4df1-bddb-98067a141448'
$usersGroup | Where-Object { ($_.ObjectGUID -split '-')[-1] -in $usersActive }

Note how the -split operator is used to split the GUID into tokens by -, with [-1] returning the last token, which -in then looks for by equality comparison in the $UsersActive array.


As an aside:

  • Allowing multiple patterns as the RHS of -like and -match - so as to return $true if any of them match - would be a helpful future improvement.

  • GitHub issue #2132 asks for just that.

CodePudding user response:

If I understand you correctly, using compare-object... This has only one match. Compare-object can be slow for large lists.

$usersgroup = 
'SamAccountName,ObjectGUID
XXXX00XX,0031e949-9120-4df1-bddb-98067a141448
XXXX01XX,0031e949-9120-4df1-bdgb-99067a141448
XXXX02XX,0031e949-9120-4df1-bdab-97067a141448' | convertfrom-csv

$usersactive = -split
'fcb483fa146b
fcb515739a2f
fcb82f1ef74c
fcc5ee8b8722
fcd3f1f471c2
fceb26a598a3
fd0b14cecd0e
98067a141448'

compare ($usersgroup.objectguid -replace '.*-') $usersactive -IncludeEqual |
  ? sideindicator -eq '=='  # order doesn't matter


InputObject  SideIndicator
-----------  -------------
98067a141448 ==
  • Related