【问题标题】:Merge/combine two lists line by line?逐行合并/组合两个列表?
【发布时间】:2017-09-26 15:18:09
【问题描述】:

我有两个存储在变量中的列表:$list1$list2,例如:

$list1:

一种 b C d

$list2:

1 2 3 4

如何将它们逐行合并在一起,最终得到:

a1 b2 c3 d4

我尝试过使用数组 (@),但它只是将它们一个接一个地组合在一起,而不是逐行组合,例如:

$list1 = @(command)
$list1 += @($list2)

【问题讨论】:

标签: list powershell merge


【解决方案1】:

您可以使用 For 循环来执行此操作,该循环使用迭代每个对象的索引,直到达到第一个对象的总数 (.count):

$list1 = 'a','b','c','d'
$list2 = 1,2,3,4

For ($i=0; $i -lt $list1.count; $i++) {
    $list1[$i]+$list2[$i]
}

输出:

a1
b2
c3
d4

如果您希望将结果转到变量中,可以将(例如)$list = 放在 For 之前。

【讨论】:

    【解决方案2】:

    如果你更喜欢流水线,你也可以在一行中完成:

    0 .. ($list1.count -1) | ForEach-Object { $list1[$_]+$list2[$_] }
    

    【讨论】:

    • 好一个班轮!但是我在运行时只得到 a1 输出(每个列表的第一行)?例如: $list1="a,b,c,d" $list2="1,2,3,4" $result=0 .. ($list1.count -1) | ForEach-Object { $list1[$_]+$list2[$_] } 回显 $result。这表明:a1
    • 您正在初始化列表错误。你的 $list1 只是一个字符串。正确的方式是:$list1 = 'a', 'b', 'c', 'd'
    【解决方案3】:

    补充Mark Wragg's helpful for-based answerMartin Brandl's helpful pipeline-based answer

    foreach.. 结合使用,范围运算符可以提供一个简洁的解决方案,而且性能也很好:

    foreach ($i in 0..($list1.count-1)) { "$($list1[$i])$($list2[$i])" }
    

    尽管首先构造了整个索引数组 - 0..($list1.count-1) - 这在具有大输入列表的情况下略微优于 for 解决方案,并且 foreachfor 都将明显快于基于管道的解决方案- 见下文。

    还要注意如何使用字符串插值(单个"..." 字符串中的变量引用和子表达式)来确保结果始终是字符串

    相比之下,如果您使用+,则决定输出类型的是LHS的类型,这可能会导致错误或不需要的输出;例如,1 + 'a' 会导致错误,因为1 是整数,而'a' 无法转换为整数。


    选读:性能考虑

    • 通常,foreachfor 解决方案明显快于基于管道(ForEach-Object 基于 cmdlet)的解决方案。

    • 流水线优雅简洁,但相对较慢。

      • 这不应该阻止您使用它们,但重要的是要意识到它们可能成为性能瓶颈。

      • 管道内存效率很高,并且对于处理不适合整个内存的大型集合,它们始终是正确的工具。

    • PSv4 引入了鲜为人知的.ForEach()集合运算符(方法),其性能介于for / foreachForEach-Object 之间 cmdlet.

    下面比较大列表(100,000 项)的相对性能;绝对时间数字会因许多因素而异,但它们应该让您大致了解:

    # Define two large lists.
    $list1 = 1..100000
    $list2 = 1..100000
    
    # Define the commands as script blocks:
    $cmds = { foreach ($i in 0..($list1.count-1))  { "$($list1[$i])$($list2[$i])" } },
            { for ($i=0; $i -lt $list1.count; $i++) { "$($list1[$i])$($list2[$i])" } },
            { 0..($list1.count -1) | ForEach-Object { "$($list1[$_])$($list2[$_])" } },
            {        (0..($list1.count-1)).ForEach({ "$($list1[$_])$($list2[$_])" }) }
    
    
    # Time each command.
    $cmds | ForEach-Object { '{0:0.0}' -f (Measure-Command $_).TotalSeconds }
    

    在运行 PSv5.1 的 2 核 Windows 10 虚拟机中,我在多次运行测试后得到以下结果:

    0.5  # foreach
    0.7  # for
    1.8  # ForEach-Object (pipeline)
    1.2  # .ForEach() operator
    

    【讨论】:

      猜你喜欢
      • 2015-07-12
      • 2020-12-19
      • 1970-01-01
      • 2017-03-23
      • 2020-02-19
      • 2011-12-07
      • 2014-03-19
      • 2013-04-29
      • 2012-02-23
      相关资源
      最近更新 更多