Home > Software design >  String comparison in PowerShell doesn't seem to work
String comparison in PowerShell doesn't seem to work

Time:03-10

I am trying to compare strings from one array to every string from the other. The current method works, as I have tested it with simpler variables and it retrieves them correctly. However, the strings that I need it to compare don't seem to be affected by the comparison.

The method is the following:

$counter = 0

for ($num1 = 0; $num1 -le $serverid_oc_arr.Length; $num1  ) {
     for ($num2 = 0; $num2 -le $moss_serverid_arr.Length; $num2  ) {
          if ($serverid_oc_arr[$num1] -eq $moss_serverid_arr[$num2]) {
              break
          }
          else {
              $counter  = 1
          }
          if ($counter -eq $moss_serverid_arr.Length) {
              $unmatching_serverids  = $serverid_oc_arr[$num1]
              $counter = 0
              break
          }
     }
}

For each string in the first array it is iterating between all strings in the second and comparing them. If it locates equality, it breaks and goes to the next string in the first array. If it doesn't, for each inequality it is adding to the counter and whenever the counter hits the length of the second array (meaning no equality has been located in the second array) it adds the corresponding string to a third array that is supposed to retrieve all strings that don't match to anything in the second array in the end. Then the counter is set to 0 again and it breaks so that it can go to the next string from the first array.

This is all okay in theory and also works in practice with simpler strings, however the strings that I need it to work with are server IDs and look like this:

289101b4-3e6c-4495-9c67-f317589ba92c

Hence, the script seems to completely ignore the comparison and just puts all the strings from the first array into the third one and retrieves them at the end (sometimes also some random strings from both first and second array).

Another method I tried with similar results was:

$unmatching_serverids = $serverid_oc_arr | Where {$moss_serverid_arr -NotContains $_}

Can anyone spot any mistake that I may be making anywhere?

CodePudding user response:

The issue with your code is mainly the use of -le instead of -lt, collection index starts at 0 and the collection's Length or Count property starts at 1. This was causing $null values being added to your result collection.

In addition to the above, $counter was never getting reset if the following condition was not met:

if ($counter -eq $moss_serverid_arr.Length) { ... }

You would need to a add a $counter = 0 outside inner for loop to prevent this.

Below you can find the same, a little bit improved, algorithm in addition to a test case that proves it's working.

$ran = [random]::new()
$ref = [System.Collections.Generic.HashSet[int]]::new()

# generate a 100 GUID collection
$arr1  = 1..100 | ForEach-Object { [guid]::NewGuid() }
# pick 90 unique GUIDs from arr1
$arr2 = 1..90 | ForEach-Object {
    do {
        $i = $ran.Next($arr1.Count)
    } until($ref.Add($i))
    $arr1[$i]
}

$result = foreach($i in $arr1) {
    $found = foreach($z in $arr2) {
        if ($i -eq $z) {
            $true; break
        }
    }
    if(-not $found) { $i }
}

$result.Count -eq 10 # => Must be `$true`

As side, the above could be reduced to this using the .ExceptWith(..) method from HashSet<T> Class:

$hash = [System.Collections.Generic.HashSet[guid]]::new([guid[]]$arr1)
$hash.ExceptWith([guid[]]$arr2)
$hash.Count -eq 10 # => `$true`

CodePudding user response:

The working answer that I found for this is the below:

$unmatching_serverids = @()
foreach ($item in $serverid_oc_arr)
{
    if ($moss_serverid_arr -NotContains $item)
    {
    $unmatching_serverids  = $item
    }
}

No obvious differences can be seen between it and the other methods (especially for the for-loop, this is just a simplified variant), but somehow this works correctly.

  • Related