Stupid PSH Trick: Diffing Lists

I have two lists of strings.  One contains values that must be in the output.  The other is the actual output, Split() into strings.  I need to ensure all elements in the first list are in the second.  Optionally, I may need to ensure the second list only contains elements of the first.  The problem with [array]::IndexOf() is that it is case sensitive, and our use case mighgt be case-insensitive.

One way is to canonicalize both lists to the same case, then sort them, and lastly, join them to compare and see if they're the same.

$string1 = [string]::Join($delim, ($list1 | % { $_.ToLower()}));
$string2 = [string]::Join($delim, ($list2 | % { $_.ToLower()}));

$string1 -eq $string 2;

Or another way is to canonicalize both lists to the same case, then use [array]::IndexOf() to ensure all elements in $list1 are in $list2, and vice versa.

function Test-SubSet {
    param ( [String[]]$list1, [String[]]$list2);
    $lcList1 = $list1 | % { $_.ToLower; }
    $lcList2 = $list2 | % { $_.ToLower; }
    $pass = $true;
    foreach ($element in $lcList1) {
        if ([array]::IndexOf($lcList2, $element) -eq -1) {
            $pass= $false;
            break;
        }
    }
    $pass;
}

My favourite doesn't require canonicalization, but it doesn't handle duplicate entries very well.   I like it because it uses [Hashatables].

$list1Hash = @{};
$list1 | % { $list1Hash[$_] = $true; }
$list2 | % {
    if ($list1Hash[$_]) {
        $list1Hash.Remove($_);
    } else {
        Log-Problem "$_ is in list2 but not in list1";
    }
}
$list1Hash.Keys | sort | % { Log-Problem "$_ is in list1 but not in list2";

List 1 goes into a hash with $true as the element values.  Anything repeated in List 1 is ignored.  Anything repeated in List 2 will case it to be marked as an incorrect entry.