2

I use arrays of arrays in a Powershell script, however, sometimes, my array of arrays, actually contains only one array. For some reason, Powershell keeps replacing that array containing one array, by just one array. I don't get it, no other scripting / coding language I ever used has done that before.

Example, this is what I do not want:

PS C:\Users\> $a = @(@(123,456,789))
PS C:\Users\> $a[0]
123

This is what I want:

PS C:\Users\> $a = @(@(123,456,789), @())
PS C:\Users\> $a[0]
123
456
789

Why do I have to force an extra empty array for Powershell to consider my array of arrays as such when it only contains one array ? This is driving me nuts !

3
  • $a = ,(123,456,789) Commented Apr 14, 2016 at 10:18
  • Sorry if it sounds stupid, but could you explain this syntax ? Even the microsoft documentation is quite evasive technet.microsoft.com/en-us/library/hh847882.aspx Commented Apr 14, 2016 at 10:26
  • 1
    @jdel PowerShell is trying to be "helpful" by flattening 1-sized arrays so you don't accidentally end up with nested structures when you don't need them Commented Apr 14, 2016 at 10:38

2 Answers 2

4

You need to put a comma as the first item:

 $a = @(, @(123,456,789) )

The reason for this is that the comma is essentially the array construction parameters. This MSDN article has more information.

Sign up to request clarification or add additional context in comments.

1 Comment

Use of the unary operator , will prevent Powershell from unrolling the array.
0

@() operator interpret its content as statements not as expression. Let us put explicit ;.

@(@(123,456,789;);)

What do you have here:

  1. 123,456,789 — binary comma operator create an array with three elements.
    Result: array [123,456,789].
  2. 123,456,789; — as expression in this statement return collection, PowerShell enumerate this collection and write collection's elements (not collection itself) to the pipeline.
    Result: three elements 123, 456 and 789 written to the pipeline.
  3. @(123,456,789;) — array subexpression operator collect all the items written to pipeline as result of invocation of nested statements and create array from them.
    Result: array [123,456,789].
  4. @(123,456,789;); — as expression in this statement return collection, PowerShell enumerate this collection and write collection's elements (not collection itself) to the pipeline.
    Result: three elements 123, 456 and 789 written to the pipeline.
  5. @(@(123,456,789;);) — array subexpression operator collect all the items written to pipeline as result of invocation of nested statements and create array from them.
    Result: array [123,456,789].

So, when you write @(collection), PowerShell return copy of collection, not collection wrapped into single element array. If you want to create array with single element, then you should use unary comma operator: ,expression. This will create single element array regardless of expression return collection or not.

Also, when you write @(a,b,c,etc), it is binary comma, who create array. Array subexpression operator just copy that array. But why do you need a copy? Is any reason, why you can not use original array? All you need for not making extra copy is just to omit @ character: (a,b,c,etc).

3 Comments

Thanks, I understand the principle. I always used the @ for making arrays, because in about_Arrays it is called the array operator. My problem is i need to build an multidimensional array, that will always behave like such, wether there is one array, or multiple arrays in it. I played around with the comma operator, but I cannot get this right.
I feel really stupid not understanding this array thing, but these two examples are confusing me even more: PS C:\Users\> $a = ,(123,456),(789) PS C:\Users\> foreach ($b in $a[0]) {write-host "--> $b"} --> 123 456 PS C:\Users\> foreach ($b in $a[1]) {write-host "--> $b"} --> 789 PS C:\Users\> $a = ,(123,456) PS C:\Users\> foreach ($b in $a[0]) {write-host "--> $b"} --> 123 --> 456 PS C:\Users\> foreach ($b in $a[1]) {write-host "--> $b"}
@jdel Important thing here is that unary comma have higher precedence than binary comma. So that ,(123,456),(789) is the same as (,(123,456)),(789). In JSON notation it will look like [[[123,456]],789]. $a[0] will be [[123,456]], $a[0][0] will be [123,456], $a[0][0][0] will be 123, $a[0][0][1] will be 456 and $a[1] will be 789.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.