gpt4 book ai didi

arrays - Powershell阵列展平如何工作?

转载 作者:行者123 更新时间:2023-12-02 23:53:46 26 4
gpt4 key购买 nike

请注意:

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:\>

我希望管道能使列表变平。但这不会发生。我究竟做错了什么?

最佳答案

回覆:

I expected the pipeline to flatten the list. But it does not happen. What am I doing wrong?


  • 实际上,当您键入$x(最后一个命令)时,确实使变平了,但确实发生了。请注意,先前的$x.Length如何为您提供2,但$x为您提供了3个要素:
  • 一个数组(显示其属性,而不是内容)
  • 项目4
  • 项目5

  • 这表明 '一级展平'确实发生了。我希望您承认这算是扁平化。
  • 现在,从您对结果的不满来看,您很想知道:

    “为什么没有一直走下去?”

  • 我也想知道这种行为,我学到的是:
  • PowerShell行为背后的明显规则:

    当脚本(包括脚本文件,脚本块,函数)的结果提供给调用者时,会在评估脚本(至少包括脚本文件,脚本块,函数)时发生“一级”拼合。
    也就是说,如果脚本生成的数组中任何项目也都是数组,则这些项目的数组将在其位置(在同级之间)被串联。这种扁平化仅在顶级数组上发生一次,因此仅其直接的“子级数组”将被扁平化,而没有任何更深的数组。

    看一下您的示例,这种扁平化实际上发生在两个语句中:
  • 在最后一条语句上,已经提到的C:\> $x,当 shell 程序执行评估并返回3个项目时(由于$x.Length评估未屈服于调用的 shell 程序,因此在$x上没有发生)
  • 也是更早的时候,使用@($x |% { $_ }).Length,它还返回了3个项目。由于% { $_ }是一个“脚本块”,它变得扁平了,它为%(它本身是ForEach-Object的别名)的调用者引入了一个新的评估方法,并给出了结果 yield 。由于.Length紧随其后,因此没有其他 yield ,因此仅导致了一次平坦化。
  • 文档?

    好吧,我找不到专门用于此行为的文档部分。我什至不确定如何查找它,因为...该机制将如何调用? “数组结果平整”?在这些关键字下找不到任何相关内容。我承认,鉴于隐式更改数据结构可能是一件非常危险的事情,因此,没有在任何地方都显眼地记录此文档是非常令人惊讶的。
  • 为什么要展平?

    由于缺少文档,我只能推测,但是考虑一下,它似乎内置在PowerShell中,实际上是其结构的一部分。总体而言,我认为通过减少所需的修改,可以更轻松地向现有代码添加更多行为。

    要详细说明,请考虑某种语言必不可少的两个属性:
  • 允许仅使用多个Write-Output添加到返回数组。尤其需要这样做是因为shell脚本一直都在处理多个项目(很明显,多行文本)。
  • 能够从现有组件/子例程中编写程序。我会直觉地想要。


  • 现在,如果不存在扁平化的行为,则将包含多个输出语句的一组语句提取到子例程中,将意味着您突然得到一个数组,该数组以前只是平面多个Write-Output。现在,如果您在原始顶级例程中没有任何输出,这将不是问题(因为您可以只对数组进行return编码),但是如果您仍然有多个Write-Output,那么这就是一个问题。需要创建一个数组变量并将每个Write-Output更改为附加变量,或者在每个提取的子例程周围使用for循环(因为ForEach-Object,AKA %ForEach在其内部范围内运行)。

    可能针对此问题的另一种解决方案可能是特殊的运算符(如JavaScript的 yield* )返回数组的每个项目,但是PowerShell似乎选择了最少的运算符,或者为达到该目的而最少编写代码-您只需像通常一样Write-Output整个数组(因此该运算符的作用类似于单个项目的JS yield和自动用于数组的yield*)。
    我认为,某种程度上值得注意的是,这样做是以牺牲某些情况为代价的,这些情况实际上是人们不希望将数组展平的,我认为这考虑了PowerShell的极端情况。 This SO question是其中之一。有趣的是,答案实际上指向一种解决方法:它使用unary variant of the comma operator (,$someArrayItem)在“也是数组的项目”周围创建一个额外的数组,以使该数组变平而不是内部。
  • 为什么不“一直”?

    好吧,再次,没有文档,这只能是一个猜测。我能想到的是:

    虽然“平整”似乎是最需要平整的最常见情况的理想行为,但这实际上是,使人们陷入困境,而没有任何简单的解决方法(额外的 (,$someArrayItem) 添加了一个嵌套级别将是徒劳的)。那么,对于不需要扁平化的人来说,摆脱这种麻烦的唯一方法就是使用不同于数组的数据结构。这会有点昂贵。

    这里有点离题:
    它可能太如意了,但是如果需要的话,这种令人惊讶的行为并不是PowerShell无法摆脱的。例如,它可以引入某种类型的数组,该数组永远不会自动变平(仍然可以使用显式语句对其进行显式变平)。为此,顺便说一句,我觉得比较合适的是一个新的基于括号的运算符(类似于@(...),例如!(...)),因为使用(,$item)表示单个数组似乎有点奇怪(在某些语言中,例如JavaScript [,$item]表示长度为2的数组-未定义第一项)。
  • 关于arrays - Powershell阵列展平如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50933517/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com