【问题标题】:A dictionary inside of a dictionary in PowerShellPowerShell中字典内的字典
【发布时间】:2022-03-11 07:02:13
【问题描述】:

所以,我对 PowerShell 比较陌生,只是不知道如何使用数组/列表/哈希表。我基本上想做Python描绘的以下事情:

entries = {
    'one' : {
        'id': '1',
        'text': 'ok'
    },
    'two' : {
        'id': '2',
        'text': 'no'
    }
}

for entry in entries:
    print(entries[entry]['id'])

输出:

1

2


但这在 PowerShell 中是如何工作的?我尝试了以下方法:

$entries = @{
    one = @{
        id = "1";
        text = "ok"
    };
    two = @{
        id = "2";
        text = "no"
    }
}

现在我不知道如何访问这些信息。

foreach ($entry in $entries) {
   Write-Host $entries[$entry]['id']
}

=> 错误

【问题讨论】:

  • 你可以遍历你的哈希的.Keys属性,或者你可以使用.GetEnumerator()
  • (我建议接受 Mathias 的回答,因为它直接回答了您的问题并提供了有用的一般技巧)。

标签: powershell dictionary hashtable enumeration


【解决方案1】:

PowerShell 防止对字典进行隐式迭代以避免意外“展开”。

您可以通过显式调用 GetEnumerator() 来解决此问题并循环遍历包含的键值对:

foreach($kvp in $entries.GetEnumerator()){
    Write-Host $kvp.Value['id']
}

对于更接近 Python 示例的内容,您还可以提取键值并对其进行迭代:

foreach($key in $entries.get_Keys()){
    Write-Host $entries[$key]['id']
}

注意:您会发现迭代 $entries.Keys 也可以,但我强烈建议 永远不要 使用它,因为 PowerShell 通过属性访问解析字典键,所以如果字典包含一个带有键 "Keys" 的条目:

$entries = @{
    Keys = 'a','b'
    a = 'discoverable'
    b = 'also discoverable'
    c = 'you will never find me'
}

foreach($key in $entries.Keys){ # suddenly resolves to just `'a', 'b'`
    Write-Host $entries[$key]
}

你只会看到输出:

discoverable
also discoverable

不是Keysc 条目

【讨论】:

  • 很遗憾 about_Hash_Tables 没有提到Get_Keys()
  • @SantiagoSquarzon 感谢您自愿提供文档工作 ;-)
  • 这是涵盖哈希表/字典条目枚举的规范答案的良好候选者。我可以建议在答案中提到术语“哈希表”/“哈希表”,也许还有 IDictionary 接口作为共同点?至于为什么带有键 Keys 的条目不幸遮蔽了原生类型 .Keys 属性(Values 同上)背后的背景故事,请参阅 GitHub issue #7758。请注意,相比之下,成员枚举功能正确,并优先考虑类型原生属性。
  • 至于文档工作:.get_Keys() / .get_Values() 的替代方案是 .PSBase.Keys / .PSBase.Values,而 .PSBase.Keys is 已在 @987654322 中提及@: "如果键名与 HashTable 类型的属性名之一冲突,您可以使用PSBase 访问这些属性。例如,如果键名是keys,并且您想返回 Keys 的集合,请使用以下语法:$hashtable.PSBase.Keys" /cc @SantiagoSquarzon
【解决方案2】:

用一个利用member-access enumeration 的更简洁的替代方案来补充Mathias R. Jessen's helpful answer

# Implicitly loops over all entry values and from each 
# gets the 'Id' entry value from the nested hashtable. 
$entries.Values.Id  # -> 2, 1

注意:与.Keys.get_Keys() 一样,您可以选择常规使用.get_Values() 而不是.Values,以避免字面上命名为Values 的键出现问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多