【问题标题】:Tuples/ArrayList of pairs元组/数组列表对
【发布时间】:2019-06-19 18:58:31
【问题描述】:

我实际上是在尝试创建一个配对列表,这被证明是非常困难的

在任何人提到 Hashtables 之前请注意,会有我不关心的重复项。

例如,如果我这样做

$b = @{"dog" = "cat"}

我明白了

名称 值 ---- ----- 狗猫

这很好。但是,我无法添加类似

$b += @{"dog" = "horse"}

项目已添加。字典中的键:'dog' 正在添加的键:'dog'

我只是想创建一个数据表我可以使用.Add()+= 之类的东西添加到

【问题讨论】:

    标签: arrays list powershell hashtable


    【解决方案1】:

    如果您想要一个元组列表,我建议您实际构建一个 tuples 列表:

    $list = @()
    
    $tuple1 = New-Object 'Tuple[String,String]' 'dog', 'cat'
    $tuple2 = New-Object 'Tuple[String,String]' 'dog', 'horse'
    
    $list += $tuple1
    $list
    
    # Output:
    #
    # Item1 Item2 Length
    # ----- ----- ------
    # dog   cat        2
    
    $list += $tuple2
    $list
    
    # Output:
    #
    # Item1 Item2 Length
    # ----- ----- ------
    # dog   cat        2
    # dog   horse      2
    

    请注意,在此示例中,$list 是一个常规数组,这意味着,正如@mklement0 在他的回答中指出的那样,使用+= 赋值运算符附加到它之后,将重新创建大小增加 1 的数组,将新的项放入新的空槽中,然后替换原来的数组。对于少量追加操作,这通常不是什么大问题,但随着追加操作数量的增加,性能影响变得显着。

    使用ArrayList 而不是普通数组可以避免这个问题:

    $list = New-Object Collections.ArrayList
    
    $tuple1 = New-Object 'Tuple[String,String]' 'dog', 'cat'
    $tuple2 = New-Object 'Tuple[String,String]' 'dog', 'horse'
    
    $list.Add($tuple1) | Out-Null
    $list
    
    # Output:
    #
    # Item1 Item2 Length
    # ----- ----- ------
    # dog   cat        2
    
    $list.Add($tuple2) | Out-Null
    $list
    
    # Output:
    #
    # Item1 Item2 Length
    # ----- ----- ------
    # dog   cat        2
    # dog   horse      2
    

    ArrayList 对象的Add() 方法输出附加项目的索引。 Out-Null 抑制在大多数情况下不需要的输出。如果您想使用这些索引号,可以将它们收集到一个变量中,而不是丢弃它们 ($i = $list.Add($t1))。

    如果你想避免一直指定新元组的类型,你可以将它包装成一个可重用的函数,如下所示:

    function New-Tuple {
        Param(
            [Parameter(Mandatory=$true)]
            [ValidateCount(2,2)]
            [string[]]$Values
        )
    
        New-Object 'Tuple[String,String]' $Values
    }
    
    $tuple1 = New-Tuple 'dog', 'cat'
    $tuple2 = New-Tuple 'dog', 'horse'
    

    或者,以更通用的方式,像这样:

    function New-Tuple {
        Param(
            [Parameter(
                Mandatory=$true,
                ValueFromPipeline=$true,
                ValueFromPipelineByPropertyName=$true
            )]
            [ValidateCount(2,20)]
            [array]$Values
        )
    
        Process {
            $types = ($Values | ForEach-Object { $_.GetType().Name }) -join ','
            New-Object "Tuple[$types]" $Values
        }
    }
    
    $tuples = ('dog', 'cat'), ('dog', 'horse') | New-Tuple
    

    【讨论】:

      【解决方案2】:

      Persistent13's helpful answer 提供了一种有效且高效的解决方案 - 尽管有点晦涩。

      创建一个散列表的数组是最简单的解决方案,但重要的是要注意“扩展”数组意味着隐式重新创建它,因为数组是固定大小的数据结构,多次迭代可能会成为性能问题:

      # Using array-construction operator ",", create a single-element array
      # containing a hashtable
      $b = , @{ dog = "cat"} 
      
      # "Extend" array $b by appending another hashtable.
      # Technically, a new array must be allocated that contains the original array's
      # elements plus the newly added one.
      $b += @{ dog = "horse"}
      

      This GitHub issue 讨论了一个潜在的未来增强功能,以使 PowerShell 在本机上支持一种高效可扩展的类似列表的数据类型,或者甚至 默认 为这种数据类型。 (从 Windows PowerShell v5.1 / PowerShell Core 6.2.0 开始,PowerShell 默认为固定大小的数组,类型为 [object[]])。

      【讨论】:

        【解决方案3】:

        感谢 mklement0,下面可能是最简单的解决方案

        $b = , @{ dog = "cat"} 
        $b += @{ dog = "horse"}
        

        Persistent13 的方法也产生了一条简单的路线

        $ht = @{foo='bar'}
        $list = [System.Collections.Generic.List[hashtable]]::new()
        $list.Add($ht)
        $list.Add($ht)
        $list.Add($ht)
        $list
        

        我想我只是惊讶于没有更根深蒂固的方法来获得我认为非常基本/标准的对象类型

        【讨论】:

          【解决方案4】:

          我相信哈希表列表应该可以满足您的需求。

          $ht = @{foo='bar'}
          $list = [System.Collections.Generic.List[hashtable]]::new()
          $list.Add($ht)
          $list.Add($ht)
          $list.Add($ht)
          $list
          

          【讨论】:

          • 谢谢,但在尝试定义 $list Method invocation failed because [System.Collections.Generic.List1[[System.Collections.Hashtable, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]] doesn't contain a method named 'new'. At line:1 char:1 + $results = [System.Collections.Generic.List[hashtable]]::new() + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound时出现以下错误@
          • 那么您使用的是旧版本的 PowerShell。你必须使用$list = New-Object -TypeName 'System.Collections.Generic.List[hashtable]'
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-11
          • 2012-10-31
          • 1970-01-01
          • 2014-07-04
          相关资源
          最近更新 更多