Search code examples
powershellarraylistpowershell-3.0powershell-4.0

Creating Arraylist of Arraylist by slicing existing arraylist


I have the following variable defined

$A =  New-Object -TypeName "System.Collections.ArrayList"

Now I add n elements to it :

$A.Add(1..n)

Now I want to divide $A into p parts of k elements each(The last one might have lesser elements if p*k>$A.count). How do I do that?


Solution

  • You can use a function to split an array into several smaller arrays. Below a slighty adapted version of that function found here:

    function Split-Array {
        [CmdletBinding(DefaultParametersetName = 'ByChunkSize')]
        Param(
            [Parameter(Mandatory = $true, Position = 0)]
            $Array,
    
            [Parameter(Mandatory = $true, Position = 1, ParameterSetName = 'ByChunkSize')]
            [ValidateRange(1,[int]::MaxValue)]
            [int]$ChunkSize,
    
            [Parameter(Mandatory = $true, Position = 1, ParameterSetName = 'ByParts')]
            [ValidateRange(1,[int]::MaxValue)]
            [int]$Parts
        )
    
        $items = $Array.Count
        switch ($PsCmdlet.ParameterSetName) {
            'ByChunkSize'  { $Parts = [Math]::Ceiling($items / $ChunkSize) }
            'ByParts'      { $ChunkSize = [Math]::Ceiling($items / $Parts) }
            default        { throw "Split-Array: You must use either the Parts or the ChunkSize parameter" }
        }
    
        # when the given ChunkSize is larger or equal to the number of items in the array
        # use TWO unary commas to return the array as single sub array of the result.
        if ($ChunkSize -ge $items) { return ,,$Array }
    
        $result = for ($i = 1; $i -le $Parts; $i++) {
            $first = (($i - 1) * $ChunkSize)
            $last  = [Math]::Min(($i * $ChunkSize) - 1, $items - 1)
            ,$Array[$first..$last]
        }
    
        return ,$result
    }
    

    In your case you could use it like:

    $p = 4  # the number of parts you want
    $subArrays = Split-Array $A.ToArray() -Parts $p
    

    or

    $k = 4  # the max number items in each part
    $subArrays = Split-Array $A.ToArray() -ChunkSize $k