Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different length arrays to one CSV

If you have multiple arrays of different length, how can you export these to a single csv in powershell?

Array1 = 1,2,3 
Array2 = Bob,smithy,Alex,Jeremy 
Array3 = yes,no

Output CSV

Number  Name  Valid 
———————————————————  
1      Bob    Yes  
2      Smithy no  
3      Alex
       Jeremy

Basically each array would be in its own header column.

Tried lines like

Array1 | Select-Object Number | export-csv -Path C:\Path

This works for singular arrays to singular csv files

But if I try

Array1, Array2, Array3 | Select-Object Number, Name, Valid | export-csv -Path C:\Path

I just get the header names and no values in the columns

like image 937
Bob Johnson Avatar asked Jan 31 '26 05:01

Bob Johnson


1 Answers

One way to do it is with a for loop.

$Array1 = 1, 2, 3
$Array2 = 'Joe Bloggs', 'John Doe', 'Jane Doe'
$Array3 = 'Yes', 'No'

$export = for($i = 0; $i -lt [Linq.Enumerable]::Max([int[]] ($Array1.Count, $Array2.Count, $Array3.Count)); $i++) {
    [pscustomobject]@{
        Number = $Array1[$i]
        Name   = $Array2[$i]
        Valid  = $Array3[$i]
    }
}
$export | Export-Csv path\to\csv.csv -NoTypeInformation

Another example using a function, the logic is more or less the same except that there is more overhead involved, since this function can handle an indefinite amount of arrays coming from the pipeline.

function Join-Array {
    [CmdletBinding()]
    param(
        [parameter(ValueFromPipeline, Mandatory)]
        [object[]] $InputObject,

        [parameter(Mandatory, Position = 0)]
        [string[]] $Columns
    )

    begin {
        $inputDict = [ordered]@{}
        $index = 0
    }
    process {
        try {
            if ($MyInvocation.ExpectingInput) {
                return $inputDict.Add($Columns[$index++], $InputObject)

            }

            foreach ($item in $InputObject) {
                $inputDict.Add($Columns[$index++], $item)
            }
        }
        catch {
            if ($_.Exception.InnerException -is [ArgumentNullException]) {
                $errorRecord = [Management.Automation.ErrorRecord]::new(
                    [Exception] 'Different count between input arrays and Columns.',
                    'InputArrayLengthMismatch',
                    [Management.Automation.ErrorCategory]::InvalidOperation,
                    $InputObject
                )
                $PSCmdlet.ThrowTerminatingError($errorRecord)
            }
            $PSCmdlet.ThrowTerminatingError($_)
        }
    }
    end {
        foreach ($pair in $inputDict.GetEnumerator()) {
            $count = $pair.Value.Count
            if ($count -gt $max) {
                $max = $count
            }
        }

        for ($i = 0; $i -lt $max; $i++) {
            $out = [ordered]@{}
            foreach ($column in $inputDict.PSBase.Keys) {
                $out[$column] = $inputDict[$column][$i]
            }
            [pscustomobject] $out
        }
    }
}

The usage would be pretty easy, the arrays to join / zip can be passed through the pipeline and the desired column names defined positionally:

$Array1 = 1, 2, 3
$Array2 = 'Joe Bloggs', 'John Doe', 'Jane Doe'
$Array3 = 'Yes', 'No'
$Array4 = 'hello', 'world', 123, 456

$Array1, $Array2, $Array3, $Array4 | Join-Array Number, Name, Valid, Test |
    Export-Csv path\to\csv.csv -NoTypeInformation
like image 160
Santiago Squarzon Avatar answered Feb 01 '26 22:02

Santiago Squarzon