0

Regarding this topic, I've so far found two questions here which relate to my question, but not fully. I have found how to initialize a large array, here. Additionally, I've found how to declare a multi-dimensional array, here. I've yet to find a solution which covers how to both declare AND initialize a multi-dimensional array. In my case, I need an array[10][10] with all elements initialized to zero. Currently I do this as follows:

$array = @(
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
)

This, of course, is completely un-scalable. From the first question, I found that $arr = @(0) * 10000 works for regular arrays, so I tried to use $array = @(@(0) * 10) * 10, and while this runs just fine, trying to access any element of this array gives me a 'Cannot modify because element is null' error.

To clarify, this code:

$array = @(
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    @(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
)
Write-Host "$($null -eq $array[1][5])"

returns False, where as this code:

$array = @(@(0) * 10) * 10
Write-Host "$($null -eq $array[1][5])"

returns True.

What is the definitive, correct, scalable way to declare and initialize an array with N-dimensions?

martorad
  • 165
  • 1
  • 12
  • Classic PowerShell gotcha: use the [comma operator](https://stackoverflow.com/questions/42772083/why-is-a-leading-comma-required-when-creating-an-array): `$array = ,@(,@(0) * 10) * 10`, see also: [Why is a leading comma required when creating an array?](https://stackoverflow.com/a/42772846/1701026) – iRon Oct 18 '21 at 08:41
  • Does this answer your question? [Return Multidimensional Array From Function](https://stackoverflow.com/questions/40220590/return-multidimensional-array-from-function) and/or [Why does PowerShell flatten arrays automatically?](https://stackoverflow.com/a/57023751/1701026) – iRon Oct 18 '21 at 08:58
  • FYI: [PowerShell Gotchas](https://stackoverflow.com/a/69617202/1701026) – iRon Oct 18 '21 at 14:07
  • @iRon very useful! I actually only knew a couple of those, so reading about the rest is quite nice. Thanks! – martorad Oct 18 '21 at 14:33

1 Answers1

1

What is the definitive, correct, scalable way to declare and initialize an array with N-dimensions?

$2DArray = [int[,]]::new(10,10)

This will create a 10x10 2D array that you can index into like this:

$null -ne $2DArray[1,5]

For a jagged array (an array of arrays), use the unary array operator ,:

$jaggedArray = ,((0) * 10) * 10 

This will create a 10-item array consisting of 10 10-item arrays of 0 that you can index into like this:

$null -ne $jaggedArray[1][5]

As mentioned in the comments, due to PowerShell's tendency to flatten any arrays, it might be better to devise a custom data type for collecting specific information:

using namespace System.Collections.Generic

class SensorSink {
  [List[int[]]]$Measurements = [List[int[]]]::new(10)

  AcceptTelemetry([int[]]$telemetry){
    if($telemetry.Count -ne 10){
      throw [ArgumentException]::new('telemetry', "Expected exactly 10 data points, received $($telemetry.Count)")
    }

    $this.Measurements.Add($telemetry)
  }
}
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • This is all incredibly confusing for a Powershell newbie like me. Between regular and jagged arrays, hash tables, `,` vs `@()`. That said, your solution works perfectly. You really are a Powershell guru. – martorad Oct 18 '21 at 09:30
  • 2
    @martorad FWIW you almost _never_ need nested arrays like this. Chances are whatever problem you're trying to solve, you'd probably be better off with an array of objects (custom or based of a `class` definition) describing the "inner" array values. But you'd have to tell us what you're actually trying to achieve with your 10x10 array if you what suggestions in that direction :) – Mathias R. Jessen Oct 18 '21 at 09:35
  • I'm getting 10 values from 10 sensors on a microcontroller. I'm then receiving these values over Serial and reading them into my Powershell script. I receive these values 10 times, hence my 10x10 dimensionality. In truth, a regular array of 100 elements would absolutely suffice here, I decided to make it 2D purely because it _looks nicer_. – martorad Oct 18 '21 at 09:38
  • 1
    Final update, I first implemented the jaggedArray solution, which worked, but since I'm converting all my data to a JSON, it flattened it to 1 array of 100 elements. I then implemented the list of string arrays solution and that worked like a charm. Thank you! – martorad Oct 18 '21 at 12:19