哈希表 - 组合未知数量的哈希表

时间:2021-01-16 05:18:47

标签: powershell hashtable

我正在尝试以编程方式将未知数量的哈希表组合成一个更大的哈希表。每个单独的表将具有相同的键。我尝试只是附加它,但它会引发关于重复键的错误。

ForEach ($Thing in $Things){
  $ht1 = New-Object psobject @{
    Path = $Thing.path
    Name = $Thing.name
  }
  $ht2 += $ht1
}

抛出错误

Item has already been added. Key in dictionary: 'Path'  Key being added: 'Path'

最终的结果是我以后可以说

ForEach ($Item in $ht2){
  write-host $Item.path
  write-host $Item.name
}

4 个答案:

答案 0 :(得分:1)

将我的评论转换为答案。

您可能想要创建的是一个哈希表数组。数组中的每个项目对于每个键都可以有自己的值。这种结构可以按照您在帖子末尾的查询中指明的方式使用。

试试这个:

$things = gci $home

$ht2 = @()       # create empty array

ForEach ($Thing in $Things){
  $ht1 = New-Object psobject @{
    Path = $Thing.PSpath
    Name = $Thing.name
  }
  $ht2 += $ht1
}

$ht2

请注意,我将 .path 更改为 .PSpath 以使示例工作。请注意,$ht2 在循环之前被初始化为一个空数组。

答案 1 :(得分:0)

如果已经存在具有相同键的元素,则确实将元素添加到哈希表fails。要克服这个问题,首先要查看元素是否存在。像这样,

if(-not $ht2.ContainsKey($thing.name)){
    $ht2.Add($thing.name, $thing.value)
}

也可以使用项目属性 [] 进行检查,因为它为不存在的元素返回 $null。像这样,

if($ht2[$thing.name] -eq $null){
    $ht2.Add($thing.name, $thing.value)
}

答案 2 :(得分:0)

如果这真的是关于合并 Hashtables 就像标题所说的那样,那么基本上你有两个选项可以将第二个哈希表中的条目添加到第一个。

1.使用静态方法 Add()(第一项 'wins')

这已经在 vonPryz's answer 中解释过,但简而言之:

在哈希表中添加一个条目,其键已经存在于哈希中,Add() 方法将抛出异常,因为哈希中的所有键都必须是唯一的。
为了克服这个问题,您需要检查是否存在具有该键的条目,如果存在,则不要从第二个散列中添加条目。

    foreach ($key in $secondHash.Keys) {
        if (!$firstHash.Contains($key)) {
            # only add the entry if the key (name) did not already exist
            $firstHash.Add($key, $secondHash[$key])  
        }
    }

这样,第一个哈希表中已有的所有条目都不会被覆盖,第二个哈希表中的重复条目将被丢弃。

2.无论是否存在都覆盖/添加(最后一项“获胜”)

您也可以选择“合并”条目,而无需像这样检查:

    foreach ($key in $secondHash.Keys) {
        # always add the entry even if the key (name) already exist
        $firstHash[$key] = $secondHash[$key]
    }

这样,如果第一个散列中已经存在一个条目,它的值将被第二个散列中的值覆盖。 如果该条目尚不存在,则将其简单地添加到第一个哈希表中。

但是,如果您想合并而不跳过或覆盖现有值怎么办?

在这种情况下,您需要想出一些方法来为要添加的条目创建唯一键。
像这样:

    foreach ($key in $secondHash.Keys) {
        if ($firstHash.Contains($key)) {
            # ouch, the key already exists.. 
            # now, we only want to add this if the value differs (no point otherwise)
            if ($firstHash[$key] -ne $secondHash[$key]) {
                # add the entry, but create a new unique key to store it under first
                # this example just adds a number between brackets to the key
                $num = 1
                do {
                    $newKey = '{0}({1})' -f $key, $num++
                } until (!$firstHash.Contains($newKey))
                # we now have a unique new key, so add it
                $firstHash[$newKey] = $secondHash[$key]
            }
        }
        else {
            # no worries, the key is unique
            $firstHash[$key] = $secondHash[$key]
        }
    }

答案 3 :(得分:0)

正如@WalterMitty 指出的那样,结果我需要的是一个哈希表数组,而不是一个哈希表哈希表。我的最终代码是:

#varibale name ht2 保留以明确它与原始问题的关系

$ht2 = @()

ForEach ($Thing in $Things){
  $ht1 = New-Object psobject @{
    Path = $Thing.path
    Name = $Thing.name
  }
  $ht2 += $ht1
}