在Powershell中展平嵌套数组

时间:2015-11-05 11:51:03

标签: powershell

鉴于此输入:

$values = @(1, @(2, 3), $null, @(@(4), 5), 6)

上创建干净的迭代/管道有什么必要
1,2,3,4,5,6

条件:

  • 不应在输出中包含$null
  • 即使输入为$ null或所有输入的值都为$ null,它也会导致空数组。

加成:

  • 它应显示[1,2,3,4,5,6]
  • 的结果ConvertTo-Json -Compress
  • 最好是清洁和令人难忘的,即非拜占庭式的管道操作首选,不依赖于自定义功能,如果可能的话。

我已经看过Flatten array in PowerShell,那里的解决方案似乎不符合条件。

5 个答案:

答案 0 :(得分:6)

@(1, @(2, 3), $null, @(@(4), 5), 6) | %{$_} | ?{$_ -ne $null}

输出:

1
2
3
4
5
6

默认情况下,ForEach-Object cmdlet(%)会对数组进行展平。

答案 1 :(得分:3)

为了完整起见,因为它可以帮助另一个用户,我想要包含一个非常简单的递归函数,它涵盖了除了...之外的大多数条件。

  

最好是干净且令人难忘的,即非拜占庭式的管道操作首选,如果可能的话,不依赖于自定义功能。

我知道 [你]本可以做到[你的]自己但也许它可以帮助别人。在谈到PowerShell时,我已经看到过这种情况,称为展开数组。如果你继续搜索,这个词可能有助于结出更多的果实。

使用$input我们的意图,我们做了一个相当简单的功能。如果传递的元素之一是数组元素,那么我们再次调用该函数,直到我们将其缩减为原始值。

function Flatten-Array{
    $input | ForEach-Object{
        if ($_ -is [array]){$_ | Flatten-Array}else{$_}
    } | Where-Object{![string]::IsNullorEmpty($_)}
    # | Where-Object{$_} would also work.
}

所以样本调用将是

@(1, @(2, 3), $null, @(@(4), 5), 6) | Flatten-Array | ConvertTo-Json -Compress

哪个网[1,2,3,4,5,6]$null涵盖了几个简单Where条款之一。

答案 2 :(得分:3)

您可以使用递归命令执行此操作:

$values = (1, (2, 3), $null, (,4, 5), 6)

$values|&{
    process{
        if($null -ne [System.Management.Automation.LanguagePrimitives]::GetEnumerator($_)){
            $_|&$MyInvocation.MyCommand.ScriptBlock
        }elseif($null -ne $_){
            $_
        }
    }
}

但你应该确定,你没有传递这样的信息作为输入:

$values[0]=$values=,0

答案 3 :(得分:1)

注意:不要使用$input作为变量名称,它是一个自动管道枚举器,它不会按照您的预期行事。< / p>

两轮流水线操作(即使用ForEach-Object)将为您展平该结构,ConvertTo-Json -Compress将自动省略$null值:

PS C:\> $NestedArray = @(1, @(2, 3), $null, @(@(4), 5), 6)
PS C:\> $FlatArray   = $NestedArray | ForEach-Object { $_ } | ForEach-Object { $_ }
PS C:\> $FlatArray | ConvertTo-Json -Compress
[1,2,3,4,5,6]

答案 4 :(得分:1)

这是一个不使用管道传输的递归Flatten-Array函数:

$values = @(1, @(2, 3), $null, @(@(4), 5), 6)

function Flatten-Array{
    param (
        [array] $inputArray 
    )

    foreach ($item in $inputArray){ 
        # skip $nulls
        if ($item -ne $null) {
            # recurse for arrays
            if ($item.gettype().BaseType -eq [System.Array]) {
                Flatten-Array $item
            }
            else {
            # output non-arrays
                $item
            }
        }
    }
}

Flatten-Array $values | %{$_.gettype()}