鉴于此功能:
> function Get-ArrayOfArrays() {
(1,2),(3,4) | % { $_ }
}
我希望返回类型是一个数组数组。但是,内部数组似乎正在扩展到管道中:
> Get-ArrayOfArrays | % { $_.GetType().Name }
Int32
Int32
Int32
Int32
实际上,运行内联管道会产生以下结果:
> (1,2),(3,4) | % { $_ }
Object[]
Object[]
我发现如果我在foreach中使用return关键字,我可以达到预期的结果:
> function Get-ArrayOfArraysWithReturn() {
(1,2),(3,4) | % { return $_ }
}
> Get-ArrayOfArraysWithReturn | % { $_.GetType().Name }
Object[]
Object[]
这种行为似乎是“如果从具有未捕获对象的函数返回,并且这些对象碰巧是数组,那么展开它们”。这是“做什么是有用的 - 最常用的”设计决策之一吗?或者我错过了其他什么?
答案 0 :(得分:4)
(1,2),(3,4) | % {$_}
导致函数输出(1,2)和(3,4) - 与此函数相同:
function foo {
1,2
3,4
}
踢球者是这些数组中的每一个都将其内容展开(展平)作为输出对象的函数过程的一部分,例如:
PS> foo | %{$_.GetType().Name}
Int32
Int32
Int32
Int32
这与您在执行此操作时在主机上看到的内容类似:
PS> 1,2
1
2
展开数组,以便显示数组的每个元素。以下应该做你想要的:
function Get-ArrayOfArrays() {
(1,2),(3,4)
}
当(1,2),(3,4)点击功能输出时,它会展开一次,输出(1,2)和(3,4)。可用于解决集合展开的另一种技术是使用,
运算符将集合包装在另一个单个元素集合中,以保留原始集合的形状,例如:
PS> function foo { ,((1,2),(3,4)) }
PS> foo | gtn
Object[]
答案 1 :(得分:0)
我打算问一个类似的问题,即“你如何阻止PowerShell展开/加入/连接数组?”。
我发现,交互式解释器会在之前执行额外的步骤,然后在控制台中打印结果:
例如
> (1, 2), (3, 4)
1
2
3
4
这意味着它已经展开一次:
[ 1, 2 ] ++ [ 3, 4 ] == [ 1, 2, 3, 4 ]
因此,解释器打印的内容不一定是代码的真实输出。
例如,以下代码
1, 2, 3 | ForEach-Object { $_, ($_ * 2) }
取前三个整数,并为每个整数提供两个数字[ x, x * 2 ]
的列表。结果是:
[ 1, 2, 2, 4, 3, 6 ]
但是我想要以下输出:
[ [ 1, 2 ], [ 2, 4 ], [ 3, 6 ] ]
我使用了逗号,
运算符,正如Keith Hill建议的那样:
$list = 1, 2, 3 | ForEach-Object { , ($_, ($_ * 2)) }
因为我们为每个输入返回一个数组的数组:
1 -> [ [ 1, 2 ] ]
2 -> [ [ 2, 4 ] ]
3 -> [ [ 3, 6 ] ]
我们希望它只展开一次,以便$list
等于:
[ [ 1, 2 ] ] + [ [ 2, 4 ] ] + [ [ 3, 6 ] ] == [ [ 1, 2 ], [ 2, 4 ], [ 3, 6 ] ]
我们可以测试它是
> $list[0] # get first element of list, should be [ 1, 2 ]
1
2
> $list[2][1] # from the third elem, [ 3, 6 ], get 2nd elem, should be 6
6
但是,当解释器打印列表时,它会再次展开它:
[ 1, 2 ] ++ [ 2, 4 ] ++ [ 3, 6 ] == [ 1, 2, 2, 4, 3, 6 ]
所以我们得到了
> $list
# prints [ 1, 2, 2, 4, 3, 6 ]