Aaron Hu
Aaron Hu

Reputation: 75

PowerShell enumerate an array that contains only one inner array

Conside this: This is one array and contains only one item. And the item of the array is another array(I call it list object). I want to get the only list object inside an array.

I use foreach to get the list, but it treates the list object as an array and return the first item of the list object.

$OSName1 = @(
    @("win2008r2")
)
$OSName2 = @(
    @("win2008r2"),
    @("win2012")
)


foreach ($osname in $OSName1) {
    write-host $osname[0]
}

foreach ($osname in $OSName2) {
    write-host $osname[0]
}

I expect the output of result is: win2008r2 win2008r2 win2012

But the real result is w win2008r2 win2012 Why powershell auto expands the inside array to it parent?

Upvotes: 4

Views: 910

Answers (2)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200473

You're misunderstanding how array construction in general and the @() operator in particular work in PowerShell. If you take a look at the value of your 2 array variables you'll notice that only the second one has nested arrays:

PS C:\> ConvertTo-Json $OSName1
[
    "win2008r2"
]
PS C:\> ConvertTo-Json $OSName2
[
    [
        "win2008r2"
    ],
    [
        "win2012"
    ]
]

That is because the array subexpression operator @() evaluates the nested expression and then returns the result as an array. But when you're nesting an array subexpression into another array subexpression the result of the inner subexpression is automatically unrolled upon the evalution of the outer subexpression. Because of that your first variable becomes ['win2008r2'] instead of the intended [['win2008r2']].

Your second example works the way you expect because the outer array subexpression contains not just a nested array subexpression, but an array of nested subexpressions:

@(...), @(...)
      ^
       `- this comma is what actually creates the array of arrays

The outer array subexpression unrolls only the outer array, so that the result is still an array of arrays in the end. Basically, you don't need the outer @() for the desired result. Remove it and you will get the exact same result:

$OSName2 = @("win2008r2"), @("win2012")

To get a similar result with just a single nested array you need to use the unary array construction operator:

$OSName1 = ,@("win2008r2")

Upvotes: 6

Ranadip Dutta
Ranadip Dutta

Reputation: 9183

Adding to Ansgar's explanation, you just need a nested array to achieve what you need.

$OSName1 = @(
    @("win2008r2")
)
$OSName2 = @(
    @("win2008r2"),
    @("win2012")
)


foreach ($osname in $OSName1) 
{
    $OSName
    foreach($OS2 in $OSName2 )
    {
    $OS2
    }
}

I hope it helps.

Upvotes: -1

Related Questions