【问题标题】:Why cant I store a hashtable in an arraylist?为什么我不能将哈希表存储在数组列表中?
【发布时间】:2017-07-21 16:00:29
【问题描述】:

这是我的代码

$allTests = New-Object System.Collections.ArrayList
$singleTest = @{}

$singleTest.add("Type", "Human")

1..10 | foreach {

    $singleTest.add("Count", $_)
    $singleTest.add("Name", "FooBar...whatever..$_")
    $singleTest.add("Age", $_)
    $allTests.Add($singleTest) | out-null

    $singleTest.remove("Count")
    $singleTest.remove("Name")
    $singleTest.remove("Age")
}

根据我的理解,我的循环应该在每次到达时将哈希表的副本添加到数组列表中

$allTests.Add($singleTest) | out-null

循环继续,删除一些键,这为循环的下一次迭代铺平了道路。这不是发生的事情,就像 add 命令只是添加对哈希表的引用。

如果我检查

的最终值
$allTests

这会被退回

Name                           Value                                                                                                                   
----                           -----                                                                                                                   
Type                           Human                                                                                                                   
Type                           Human                                                                                                                   
Type                           Human                                                                                                                   
Type                           Human                                                                                                                   
Type                           Human                                                                                                                   
Type                           Human                                                                                                                   
Type                           Human                                                                                                                   
Type                           Human                                                                                                                   
Type                           Human                                                                                                                   
Type                           Human     

如何解决这个问题,以便将哈希表的实际副本存储在数组列表中?

我正在寻找类似的输出

$allTests[0]

Name                           Value                                                                                                                   
----                           -----                                                                                                                   
Count                          1                                                                                                                       
Name                           FooBar...whatever..1                                                                                                    
Age                            1                                                                                                                       
Type                           Human  

$allTests[1]   

Name                           Value                                                                                                                   
----                           -----                                                                                                                   
Count                          2                                                                                                                       
Name                           FooBar...whatever..2                                                                                                    
Age                            2                                                                                                                       
Type                           Human  

【问题讨论】:

  • 在 Powershell 哈希表中是引用对象。您基本上必须创建一个新的哈希表并遍历旧的哈希表并将信息从旧的复制到新的。 $oldHash = @{} $newHash = @{} $newHash = $oldHash 执行上述操作只会使$newHash 引用$oldHash 并且对$newHash 的任何更改都将出现在$oldHash
  • 这些可能有用:Reference v Value Typesabout_Hash_Tablesthe Hashtable .NET class(包括克隆方法)

标签: loops powershell arraylist hashtable


【解决方案1】:

哈希表是引用,当您创建一个对象时,所有进一步的操作都针对该哈希表,包括尝试检索该信息。

您可以在每次循环运行时声明一个新的哈希表来解决这个问题。

$allTests = New-Object System.Collections.ArrayList

1..10 | foreach {
    $singleTest = @{}
    $singleTest.add("Type", "Human")
    $singleTest.add("Count", $_)
    $singleTest.add("Name", "FooBar...whatever..$_")
    $singleTest.add("Age", $_)
    $allTests.Add($singleTest) | Out-Null
}

或者甚至可以减少一些臃肿。

$allTests = New-Object System.Collections.ArrayList
1..10 | foreach {
    $allTests.Add(@{
        Type = "Human"
        Count = $_
        Name = "FooBar...Whatever..$_"
        Age = $_
    }) | Out-Null
}

这两个答案都会给你预期的输出。

【讨论】:

    【解决方案2】:

    @ConnorLSW 的答案在功能上是正确的。

    我为您提供了另一种解决方案,可以为您提供更大的灵活性。我发现自己构建了共享一些字段的自定义对象,因此您可以像现在一样在循环外部定义基础对象,然后在循环内部更改该实例的属性值,而不是每次运行循环都创建新对象然后像这样将它添加到您的收藏中:

    $allTests.Add($singleTest.Psobject.Copy())
    

    这会在插入之前将内容复制到新对象。现在,您引用的对象不是您在循环的下一次迭代期间更改的对象。

    【讨论】:

      【解决方案3】:

      由于哈希表是通过引用传递的,因此您只需将同一个哈希表的多个引用添加到您的数组列表中。您需要创建哈希表的新副本,然后将其添加到您的数组列表中。

      当您想将副本保存到数组列表时,一种选择是使用哈希表.clone() 方法。

      $allTests.Add($singleTest.clone()) | out-null
      

      【讨论】:

        猜你喜欢
        • 2012-11-15
        • 1970-01-01
        • 2015-07-18
        • 2011-10-05
        • 2021-10-28
        • 2015-05-26
        • 2014-04-14
        • 2011-07-30
        • 1970-01-01
        相关资源
        最近更新 更多