PowerShell应该从管道返回object []?

时间:2010-03-09 18:50:01

标签: powershell

鉴于此功能:

> 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[]

这种行为似乎是“如果从具有未捕获对象的函数返回,并且这些对象碰巧是数组,那么展开它们”。这是“做什么是有用的 - 最常用的”设计决策之一吗?或者我错过了其他什么?

2 个答案:

答案 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 ]