Combining Empty Arrays

I’ve been pulling my hair out at this one for the last few hours, seems to be down to an obscure quirk.

(EDITED)

Import this function:

Function Test-Filter
{
    [cmdletbinding()]
    Param
    (
        [Parameter(Mandatory = $true,
            ValueFromPipeline,
            Position = 0)]
        $Items
    )
    Process
    {
        $Items | Foreach-Object {
            if ($_ -eq "A")
            {
                $output += $_
            }
        }
    }
    End
    {
        if ($output.Count -gt 0)
        { Write-Output (,$output) }
    }
}

Now run this:

[Array]$arr1 = "A", "B", "C", "D" | Test-Filter | Sort
[Array]$arr2 = "E", "F", "G", "H" | Test-Filter | Sort | Select -First 1
[Array]$arr3 = 1, 2 | Test-Filter
[Array]$arr4 = "Jolly Cooperation" | Test-Filter

[Array]$combined = $arr1 + $arr2 + $arr3 + $arr4

$combined.count

Count is 1, as expected, $arr1 contains “A” and the rest are empty. Now run this:

Invoke-Command {
    [Array]$arr1 = "A", "B", "C", "D" | Test-Filter | Sort
    [Array]$arr2 = "E", "F", "G", "H" | Test-Filter | Sort | Select -First 1
    [Array]$arr3 = 1, 2 | Test-Filter
    [Array]$arr4 = "Jolly Cooperation" | Test-Filter

    [Array]$combined = $arr1 + $arr2 + $arr3 + $arr4

    $combined.count
}

Count is now 4.

This is part of a process to list patch files awaiting installation, there are four types of files but not all may be present in each patch type. Invoke-Command is required to format and log the output of the (lengthy) script but it seems to be messing with arrays somehow?

Answer is 4 not 1 in PS 5:

PS D:\Sandbox> [Array]$arr1 = "A"
[Array]$arr2 = $null
[Array]$arr3 = $null
[Array]$arr4 = $null

[Array]$combined = $arr1 + $arr2 + $arr3 + $arr4
$combined.Count
4

PS D:\Sandbox> $PSVersionTable

Name                           Value                                                                                                  
----                           -----                                                                                                  
PSVersion                      5.1.15063.726                                                                                          
PSEdition                      Desktop                                                                                                
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                                
BuildVersion                   10.0.15063.726                                                                                         
CLRVersion                     4.0.30319.42000                                                                                        
WSManStackVersion              3.0                                                                                                    
PSRemotingProtocolVersion      2.3                                                                                                    
SerializationVersion           1.1.0.1    

To lose the null arrays replace the line

[Array]$combined = $arr1 + $arr2 + $arr3 + $arr4

with something like

[Array]$combined = @($arr1,$arr2,$arr3,$arr4) | % { if ($_) {$_} }

Edited OP with working example, I thought that one did work but as something (I think my AV) tried to shut my computer down without warning I can’t be sure.

Oh, and just to further confuse things, with the above Test-Filter function:

Invoke-Command {
    [Array]$arr1 = "A", "B", "C", "D" | Test-Filter | Sort
    [Array]$arr2 = "E", "F", "G", "H" | Test-Filter | Sort | Select -First 1
    [Array]$arr3 = 1, 2 | Test-Filter
    [Array]$arr4 = "Jolly Cooperation" | Test-Filter

    [Array]$combined = $arr1 + $arr2 + $arr3 + $arr4

    Set-Variable -Name "DebugTest" -Value $combined -Scope Global

    $combined.Count
}

1

That one caused me some grief trying to debug it =/

I’ve used a Where { $_ } which seems a bit tidier but still really weird.