arrayspowershellset-intersection

PowerShell: Intersection of more than two arrays


Using PowerShell, I have 14 arrays of strings. Some of the arrays are empty. How would I get the intersection (all elements that exist in all of the arrays) of these arrays (excluding the arrays that are empty)? I am trying to avoid comparing two arrays at a time.

Some of the arrays are empty, so I do not want to include those in my comparisons. Any ideas on how I would approach this? Thank you.

$a = @('hjiejnfnfsd','test','huiwe','test2')
$b = @('test','jnfijweofnew','test2')
$c = @('njwifqbfiwej','test','jnfijweofnew','test2')
$d = @('bhfeukefwgu','test','dasdwdv','test2','hfuweihfei')
$e = @('test','ddwadfedgnh','test2')
$f = @('test','test2')
$g = @('test','bjiewbnefw','test2')
$h = @('uie287278hfjf','test','huiwhiwe','test2')
$i = @()
$j = @()
$k = @('jireohngi','test','gu7y8732hbj','test2')
$l = @()
$m = @('test','test2')
$n = @('test','test2')

My attempt to solve this (although it does not check for empty arrays):

$overlap = Compare-Object $a $b -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $c -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $d -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $e -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $f -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $g -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $h -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $i -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $j -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $k -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $l -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $m -PassThru -IncludeEqual -ExcludeDifferent
$overlap = Compare-Object $overlap $n -PassThru -IncludeEqual -ExcludeDifferent

My desired result is that test and test2 appear in $overlap. This solution does not work because it does not check if the array it is comparing is empty.


Solution

  • Note: The following assumes that no individual array contains the same string more than once (more work would be needed to address that).

    $a = @('hjiejnfnfsd','test','huiwe','test2')
    $b = @('test','jnfijweofnew','test2')
    $c = @('njwifqbfiwej','test','jnfijweofnew','test2')
    $d = @('bhfeukefwgu','test','dasdwdv','test2','hfuweihfei')
    $e = @('test','ddwadfedgnh','test2')
    $f = @('test','test2')
    $g = @('test','bjiewbnefw','test2')
    $h = @('uie287278hfjf','test','huiwhiwe','test2')
    $i = @()
    $j = @()
    $k = @('jireohngi','test','gu7y8732hbj','test2')
    $l = @()
    $m = @('test','test2')
    $n = @('test','test2')
    
    $allArrays = $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n
    
    # Initialize a hashtable in which we'll keep
    # track of unique strings and how often they occur.
    $ht = @{}
    
    # Loop over all arrays.
    $nonEmptyArrayCount = 0
    foreach ($arr in $allArrays) {
      # Loop over each non-empty array's elements.
      if ($arr.Count -gt 0) {
        ++$nonEmptyArrayCount 
        foreach ($el in $arr) {
          # Add each string and increment its occurrence count.
          $ht[$el] += 1
        }
      }
    }
    
    # Output all strings that occurred in every non-empty array
    $ht.GetEnumerator() |
      Where-Object Value -eq $nonEmptyArrayCount |
      ForEach-Object Key
    

    The above outputs those strings that are present in all of the non-empty input arrays:

    test2
    test