'Flatten array in PowerShell
Assume we have:
$a = @(1, @(2, @(3)))
I would like to flatten $a to get @(1, 2, 3).
I have found one solution:
@($a | % {$_}).count
But maybe there is a more elegant way?
Solution 1:[1]
Piping is the correct way to flatten nested structures, so I'm not sure what would be more "elegant". Yes, the syntax is a bit line-noisy looking, but frankly quite serviceable.
2020 Edit
The recommended syntax these days is to expand % to ForEach-Object. A bit more verbose but definitely more readable:
@($a | ForEach-Object {$_}).count
Solution 2:[2]
Same code, just wrapped in function:
function Flatten($a)
{
,@($a | % {$_})
}
Testing:
function AssertLength($expectedLength, $arr)
{
if($ExpectedLength -eq $arr.length)
{
Write-Host "OK"
}
else
{
Write-Host "FAILURE"
}
}
# Tests
AssertLength 0 (Flatten @())
AssertLength 1 (Flatten 1)
AssertLength 1 (Flatten @(1))
AssertLength 2 (Flatten @(1, 2))
AssertLength 2 (Flatten @(1, @(2)))
AssertLength 3 (Flatten @(1, @(2, @(3))))
Solution 3:[3]
You can use .NET's String.Join method.
[String]::Join("",$array)
Solution 4:[4]
This problem is probably most elegantly resolved with the .ForEach() array method introduced in Powershell v4.0. Performance-wise it has the advantage of not needing to construct a pipeline, so in some cases it might perform better.
> $a.ForEach({$_}).Count
3
If you already have a pipeline, the easiest way to flatten an array is to pipe it through Write-Output:
> $b = $a | Write-Output
> $b.Count
3
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ahsteele |
| Solution 2 | alex2k8 |
| Solution 3 | iraSenthil |
| Solution 4 | Bacon Bits |
