Arrays Powershell阵列平坦化是如何工作的?
请注意:Arrays Powershell阵列平坦化是如何工作的?,arrays,powershell,Arrays,Powershell,请注意: C:\> $x = @(1) C:\> $x = @($x,2) C:\> $x = @($x,3) C:\> $x = @($x,4) C:\> $x = @($x,5) C:\> $x.Length 2 C:\> @($x |% { $_ }).Length 3 C:\> $x Length : 2 LongLength : 2 Rank : 1 SyncRoot : {Sy
C:\> $x = @(1)
C:\> $x = @($x,2)
C:\> $x = @($x,3)
C:\> $x = @($x,4)
C:\> $x = @($x,5)
C:\> $x.Length
2
C:\> @($x |% { $_ }).Length
3
C:\> $x
Length : 2
LongLength : 2
Rank : 1
SyncRoot : {System.Object[] 2, 3}
IsReadOnly : False
IsFixedSize : True
IsSynchronized : False
Count : 2
4
5
C:\>
我原以为管道会把名单弄平。但事实并非如此。我做错了什么?Re:
我原以为管道会把名单弄平。但事实并非如此。我做错了什么
- 实际上,当您键入
(您的上一个命令)时,确实发生了一些平坦化。请注意,前面的$x
为您提供了2个元素,而$x.Length
为您提供了3个元素:$x
- 数组(显示其属性,而不是内容)
- 项目
4
- 项目
这表明确实发生了“一级平坦化”。我希望你能承认这算是平淡5
- 现在,从你对结果的不满来看,你相当疑惑: “为什么不‘一路走’?”
C:\>$x
,当shell执行评估并返回3项时(它没有发生在$x.Length
上,因为$x
评估没有向调用shell屈服)@($x |%{$}).Length
,它还返回了3个项目。这一个得到了平坦化,因为%{${code>是一个“脚本块”,它向调用它的%
(它本身是ForEach对象
的别名)引入了新的求值和结果。没有其他产量,因为.Length
紧随其后,所以它只导致一个水平再次变平
写入输出添加到返回数组中。这是需要的,特别是因为shell脚本始终处理多个项目(第一个明显的是多行文本)
写输出。现在,如果在原始顶级例程中没有输出,这不是问题(因为您可以只返回数组),但是如果仍然有多个写入输出,这是问题。您需要创建一个数组变量并将每个写入输出
更改为其附录,或者使用for
循环每个提取的子例程(因为ForEach对象
,也称为%
或ForEach
,在其自己的内部作用域中运行)
也许这个问题的另一种解决方案可能是使用一个特殊的操作符(如JavaScript)返回数组的每个项,但PowerShell似乎选择了最小的操作符,或者选择了最小的写入来实现这一点——您只需将整个数组正常地写入输出即可(因此,对于单个项目,该操作符的工作方式类似于JSyield
,对于数组,该操作符的工作方式类似于一个yield*
。
值得注意的是,我认为这样做是以不希望阵列被展平的情况为代价的,我想,这在很大程度上考虑了PowerShell的角情况使用。是其中之一。有趣的是,答案实际上指向了一个解决方法:它使用(,$someArrayItem)
在“也是数组的项目”周围创建一个额外数组,将该项目展平,而不是内部)
4.为什么不“一路走”?
好吧,同样,没有文档,这只能是猜测。但我能想到的是:
虽然“一路”展平似乎是最常见的需要展平的情况下所需要的行为,但默认情况下构建它确实是让人们处于不需要展平的情况下,没有任何简单的解决方法(因为额外添加嵌套级别是徒劳的)。让他们摆脱困境的唯一方法是使用不同于数组的数据结构。这将是相当昂贵的
这里有点离题:
这可能太过一厢情愿了,但如果PowerShell愿意的话,这种令人惊讶的行为并不是PowerShell无法进化出来的。对于