1

I'm trying to partition out chunks of work using PowerShell (5.0) and am having a hard time instantiating a multidimensional array.

$n = 456;
$MaxChunks = 6;

$Chunks = @();

for($x = 0; $x -lt $MaxChunks; $x++)
{    
    Write-Host "Creating chunk $x"    
    $Chunks += @();
}

$Chunks.Count always returns 0 and I cannot access anything in $Chunks by index (i.e. $Chunks[0] is null).

Ultimately, my goal is to access the array located at $Chunks[$i] and add multiple System.Data.DataRow objects to it. However, as I've said, I'm not able to access the array at that index because that array is never instantiated.

I've read through this and this but am not quite able to translate the hashtable scenario to my situation.

Community
  • 1
  • 1
swasheck
  • 4,644
  • 2
  • 29
  • 56
  • 1
    Did you see [this answer](http://stackoverflow.com/a/9397385/3905079) from your second link? That's the probably the information you need. – briantist Jan 31 '17 at 18:36
  • 2
    `$Chunks = ,@() * $MaxChunks` – user4003407 Jan 31 '17 at 19:07
  • @PetSerAl, it'll reuse the same object instance. Although it won't be a problem if the OP uses `+=` to populate those sub-arrays since `+=` recreates the array. – wOxxOm Jan 31 '17 at 19:39
  • @wOxxOm Zero length arrays are effectively read-only, so (apart from reference equality) it does not matter if it reused or not. – user4003407 Jan 31 '17 at 19:41
  • [This question](https://stackoverflow.com/questions/49955397/how-do-i-create-an-empty-array-of-arrays-in-powershell) may have an answer. – Slogmeister Extraordinaire Sep 25 '18 at 21:03

2 Answers2

5

Alternatively:

[System.Array] $chunks = [System.Array]::CreateInstance( [Int32], 3, 3 );

$chunks[0,0];
0

Not native PS, but works.

Simon Catlin
  • 2,141
  • 1
  • 13
  • 15
5
  • Replicate an empty array.
    The same object is referenced in each element but in this particular case it's not a problem because standard arrays are read-only and recreated when elements are added via +=.

    $Chunks = ,@() * $MaxChunks
    
  • Collect foreach output:

    $Chunks = @(foreach ($x in 1..$MaxChunks) { ,@() })
    

    The outer @() handles a theoretically possible case when $MaxChunks = 1.
    You can use a more verbose (arguably slower) Write-Output -NoEnumerate:

    $Chunks = @(foreach ($x in 1..$MaxChunks) { echo -NoEnumerate @() })
    
  • And in case the sub-arrays will be modified a lot, use ArrayList instead of +=:

    $Chunks = @(foreach ($x in 1..$MaxChunks) { ,[Collections.ArrayList]@() })
    

    and later:

    $Chunks[0].Add($something) >$null
    

P.S. Don't use += to generate entire arrays from scratch regardless of its size as it's a terrible method that recreates and copies the entire array each time; there's a much faster and simpler output collection via loop statements such as foreach, for, while; there's ArrayList object for the case of frequent non-sequential modifications of an array.

wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • BTW, why do you use `echo -NoEnumerate` instead of `,`? – user4003407 Feb 01 '17 at 17:42
  • Mainly because it's more verbose so less chance for a typo/overlook. Also, internally `,@()` creates two arrays, the outer one is unrolled (the overhead is negligible though so I guess I'll add it in the answer). – wOxxOm Feb 01 '17 at 18:27
  • *Also, internally `,@()` creates two arrays* The same applies for `echo -NoEnumerate @()` too. And it also have overhead of instantiating `Write-Output` cmdlet, parameter binding, etc. – user4003407 Feb 01 '17 at 18:32
  • Sounds convincing. – wOxxOm Feb 01 '17 at 18:40