如何在PowerShell中“压缩”两个数组?

20
我想在PowerShell中压缩两个数组,类似于Ruby如何实现, 这里有一个假设的操作符(我知道我们可能在谈论某种古怪的管道,但我只是想展示一个示例输出)。
PS> @(1, 2, 3) -zip @('A', 'B', 'C')
@(@(1, 'A'), @(2, 'B'), @(3, 'C'))

1
https://www.automatedops.com/blog/2017/02/09/working-with-the-collection-extension-methods-3-of-3/ - Roger Lipscombe
您想将它们保留为数组(数组的数组),还是将所有值都放在一个数组中? - Bali C
我不想合并数组。我需要将元素成对处理,希望能在后续流程中进行处理。 - Anthony Mastrean
@RogerLipscombe 看起来这个答案比自己编写函数要好。 - Matt
3
[Linq.Enumerable]::Zip((1, 2, 3), ('A', 'B', 'C'), [Func[Object, Object, Object[]]]{,$args}) 这行代码使用 LINQ 中的 Zip 方法,将两个序列(一个是数字序列,另一个是字母序列)组合成一个序列。在这里,使用了 PowerShell 对 Zip 方法的调用方式来实现。第三个参数是一个委托,它将每个组合的元素打包到一个数组中返回。 - user4003407
2个回答

28

目前没有内置的功能,自己编写函数也不建议。因此,我们将采用LINQ Zip方法并对其进行封装。

[System.Linq.Enumerable]::Zip((1, 2, 3), ('A', 'B', 'C'), [Func[Object, Object, Object[]]]{ ,$args })

这个方法可以用,但长期使用并不方便。我们可以对函数进行封装(并将其包含在我们的配置文件中?)。

function Select-Zip {
    [CmdletBinding()]
    Param(
        $First,
        $Second,
        $ResultSelector = { ,$args }
    )

    [System.Linq.Enumerable]::Zip($First, $Second, [Func[Object, Object, Object[]]]$ResultSelector)
}

而你可以简单地称之为:

PS> Select-Zip -First 1, 2, 3 -Second 'A', 'B', 'C'
1
A
2
B
3
C

使用非默认结果选择器:

PS> Select-Zip -First 1, 2, 3 -Second 'A', 'B', 'C' -ResultSelector { param($a, $b) "$a::$b" }
1::A
2::B
3::C

我将管道版本留给聪明的读者作为练习 :)

PS> 1, 2, 3 | Select-Zip -Second 'A', 'B', 'C'

干得好。至于一个假设的操作符:虽然不是一个操作符,但有人提出了对foreach_语句_的增强,类似于foreach ($elementFromArray1, $elementFromArray2 in @(1, 2, 3), @('A', 'B', 'C')) { ... } - 不幸的是,它被拒绝了 - 参见GitHub问题#14732 - mklement0
使用 PS 7.x,我们还可以使用 Linq.Enumerable.Zip 重载,输出元组,从而减轻了传递函数的需要:[Linq.Enumerable]::Zip( [int[]](1, 2, 3), [string[]]('A', 'B', 'C'))。请注意,数组必须是有类型的,否则 PowerShell 将无法找到正确的重载。 - zett42
如果您事先不知道数组的类型,则将其转换为 [object[]] 数组也可以起到作用:[Linq.Enumerable]::Zip( [object[]](1, 2, 3), [object[]]('A', 'B', 'C') ) - zett42
使用 PowerShell Core,如果我的数组在进入函数之前已经被类型化,那么它就是简单的 [Linq.Enumerable]::Zip($arr1, $arr2) - dudeNumber4

4
# Multiple arrays
$Sizes = @("small", "large", "tiny")
$Colors = @("red", "green", "blue")
$Shapes = @("circle", "square", "oval")

# The first line "zips"
$Sizes | ForEach-Object { $i = 0 }{ @{size=$_; color=$Colors[$i]; shape=$Shapes[$i]}; $i++ } `
 | ForEach-Object { $_.size + " " + $_.color + " " + $_.shape }

输出:

small red circle
large green square
tiny blue oval

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接