在 Powershell 中,您可以使用 .Add 將新的鍵/值對插入到現有的哈希中。如果散列已包含密鑰,則會導致錯誤。對于已知的鍵,所需的(由我 :)行為將是將現有值更新為提供的值。我可以用很多墨水來做到這一點。將 .Add 命令放在 try 短語中并在 catch 中更改值 - 效果很好,但是墨水的成本!
說真的,因為我在決議多個配置時到處都有這種邏輯(這是已經設定并需要更新還是新設定?),它使代碼變得混亂:
# $msHashtable is potentially empty at this point or may not contain the key
try {
$myHashtable.Add($thisKey, $thisValue)
}
catch {
$myHashtable.$thisKey = $thisValue
}
我所擁有的散列的另一個問題是:
- 假設您有一個哈希表 $motherOfAll,它最終將包含其他哈希表,而這些哈希表也將包含哈希表。
- 現在你想在哈希表的最底層插入一些東西。您首先需要檢查沿途的所有哈希表是否存在并包含正確的鍵。
- 如果沒有,您必須插入一堆空的哈希表,然后填充另一個空的哈希表……當然不是無限的,但仍然很丑陋。更亂的代碼。有沒有更好的辦法?
如果需要,我可以提供代碼,但我希望問題足夠清楚。由于在我的現實世界示例中,除了相關部分之外還有很多其他代碼,因此我現在不會發布它...
最好的事物,
老欣納克
uj5u.com熱心網友回復:
對于問題的第一部分,您已經得到了有用的答案。
這是我在第二部分的嘗試 - 如何分配嵌套哈希表的成員。在創建任何尚不存在的父哈希表時,沒有簡單的內置語法來設定嵌套值,因此我Set-TreeValue為此創建了一個可重用的函式。
function Set-TreeValue( $ht, [String] $path, $value ) {
# To detect errors like trying to set child of value-type leafs.
Set-StrictMode -Version 3.0
do {
# Split into root key and path remainder (", 2" -> split into max. 2 parts)
$key, $path = $path -split '\.', 2
if( $path ) {
# We have multiple path components, so we may have to create nested hash table.
if( -not $ht.Contains( $key ) ) {
$ht[ $key ] = [ordered] @{}
}
# Enter sub tree.
$ht = $ht[ $key ]
}
else {
# We have arrived at the leaf -> set its value
$ht[ $key ] = $value
}
}
while( $path )
}
演示:
$ht = [ordered] @{}
Set-TreeValue $ht foo.bar.baz 42 # Create new value and any non-existing parents
Set-TreeValue $ht foo.bar.baz 8 # Update existing value
Set-TreeValue $ht foo.bar.bam 23 # Add another leaf
Set-TreeValue $ht fop 4 # Set a leaf at root level
#Set-TreeValue $ht fop.zop 16 # Outputs an error, because .fop is a leaf
Set-TreeValue $ht 'foo bar' 15 # Use a path that contains spaces
$ht | ConvertTo-Json # Output the content of the hash table
輸出:
{
"foo": {
"bar": {
"baz": 8,
"bam": 23
}
},
"fop": 4,
"foo bar": 15
}
注意:我選擇創建嵌套哈希表,OrderedDictionary因為它們比常規哈希表更有用(例如,確保 JSON 輸出中的順序)。洗掉[ordered],如果你想無序哈希表(其中propably有輕微的性能優勢)。
uj5u.com熱心網友回復:
使用索引運算子按鍵參考特定條目,然后為該條目分配一個新值:
$hashtable = @{}
# this will add a new key/value entry
$hashtable['abc'] = 1
# this will overwrite the existing value associated with the key `abc`
$hashtable['abc'] = 2
如果您有一個包含許多現有呼叫的大型代碼庫,.Add($key, $value)并且希望避免重構每個呼叫,您可以修改哈希表本身的行為,使其Add行為類似于索引器:
function New-NonStrictHashTable {
return @{} |Add-Member -MemberType ScriptMethod -Name Add -Value {
param($key,$value)
$this[$key] = $value
} -Force -PassThru
}
現在你可以這樣做:
# Create hashtable with Add() overriden
$hashtable = New-NonStrictHashTable
$key,$value = 'key','value'
# This works like before
$hashtable.Add($key, $value)
# This works too now, it simply updates the existing entry
$hashtable.Add($key, 'some other value')
這適用于任何呼叫的PowerShell 腳本陳述句,$hashtable.Add()因為 ETS 方法的決議(例如我們使用 附加到哈希表的方法Add-Member)優先于底層 .NET 方法。
我所擁有的散列的另一個問題是:
- 假設您有一個哈希表 $motherOfAll,它最終將包含其他哈希表,而這些哈希表也將包含哈希表。
- 現在你想在哈希表的最底層插入一些東西。您首先需要檢查沿途的所有哈希表是否存在并包含正確的鍵。
- 如果沒有,您必須插入一堆空的哈希表,然后填充另一個空的哈希表……當然不是無限的,但仍然很丑陋。更亂的代碼。有沒有更好的辦法?
The desired behavior you describe here is found in Perl and is known as autovivification:
my %users;
# the nested hashes $users{YeOldHinnerk} and $users{YeOldHinnerk}{contact_details}
# will automatically come into existence when this assignment is evaluated
$users{YeOldHinnerk}{contact_details}{email_address} = "[email protected]"
The Wikipedia article linked above gives an example of how to implement similar behavior in C#, which can be adapted for PowerShell as follows:
Add-Type -TypeDefinition @'
using System.Collections.Generic;
public class AVD
{
private Dictionary<string, object> _data = new Dictionary<string, object>();
public object this[string key]
{
get {
if(!_data.ContainsKey(key)){
_data[key] = new AVD();
}
return _data[key];
}
set {
_data[key] = value;
}
}
}
'@
Now we can take advantage of PowerShell's native index access syntax:
PS ~> $autovivifyingHashtable = [AVD]::new()
PS ~> $autovivifyingHashtable['a']['b']['c'] = 123
PS ~> $autovivifyingHashtable['a'] -is [AVD]
True
PS ~> $autovivifyingHashtable['a']['b'] -is [AVD]
True
PS ~> $autovivifyingHashtable['a']['b']['c']
123
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/358633.html
