Добавить словарь в словарь в powershell (hashtable) - PullRequest
0 голосов
/ 14 октября 2019

У меня есть два словаря, подобных этому:

$first = @{}
$first.Add('John', 'Doe')
$first.Add('Johnny', 'Doe')


$second = @{}
$second.Add('Jack', 'Test')
$second.Add('Jacky', 'Test')

И у меня есть общий $all = @{} словарь, который обозначает все словари вместе взятые.

Пример. когда я хочу увидеть все ключи, которые $all содержит:

foreach($key in $all){
    Write-Host $key
}

Это покажет это:

John
Johnny
Jack
Jacky

пс У меня есть этот:

$all = @{}

$all_dict = @{}
$all_dict += $first
$all_dict += $second

foreach($dict in $all_dict){
    foreach($key in $dict.Key){
        $all.Add($key, $dict[$key])
    }
}

Но мне было интересно, есть ли другой способ сделать это без необходимости добавлять все словари в массив, а затем перебирать их

Ответы [ 3 ]

1 голос
/ 14 октября 2019

Я бы не стал добавлять += к хеш-таблицам, но вместо этого использовал бы ForEach-Object для хэшей .Keys. Таким образом, код можно сократить, но также вам будет проще выбрать, хотите ли вы, чтобы возможные дубликаты из Hashtable 1 ($ first) были перезаписаны значениями из второго Hashtable ($ second).

Примерно так:

$first = @{}
$first.Add('John', 'Doe')
$first.Add('Johnny', 'Doe')

$second = @{}
$second.Add('Jack', 'Test')
$second.Add('Jacky', 'Test')
$second.Add('Johnny', 'Depp')  # Duplicate key: same first name, different lastname

$all = @{}
# copy all keys and values from the $first Hashtable into $all
$first.Keys | ForEach-Object { $all[$_] = $first[$_] }

В следующей части вам нужно будет решить, что делать с дублирующимися ключами:

Метод 1

# add the stuff from Hashtable $second to it:
# this will overwrite the value if the key already exists (i.e. $second value 'wins')
$second.Keys | ForEach-Object { $all[$_] = $second[$_] }

ИЛИ используйте Метод 2

# make sure the value of the $first hashtable is NOT overwritten (i.e. $first value 'wins')
$second.Keys | ForEach-Object { if (!($all.ContainsKey($_))) { $all[$_] = $second[$_] }}

Если вы решите перезаписать (метод 1), хэш $ all будет содержать

Name                           Value                                                                                                                                                                  
----                           -----                                                                                                                                                                  
John                           Doe                                                                                                                                                                    
Jacky                          Test                                                                                                                                                                   
Johnny                         Depp                                                                                                                                                                   
Jack                           Test

Если вы выберете НЕдля перезаписи (метод 2), $ all будет

Name                           Value                                                                                                                                                                  
----                           -----                                                                                                                                                                  
John                           Doe                                                                                                                                                                    
Jacky                          Test                                                                                                                                                                   
Johnny                         Doe                                                                                                                                                                    
Jack                           Test


Edit

Существует другой подход, в котором вы полагаетесь натот факт, что возникает исключение, если вы пытаетесь добавить запись, которая уже существует. В этом случае используйте метод .Add(key, value) и оберните его внутри блока try{..} catch{..}. Без этой ошибки ошибка не позволяет заполнить хэш-таблицу $all, поскольку она останавливается на первом дублирующемся ключе, который вы пытаетесь добавить.

$second.Keys | ForEach-Object { 
    try {
        $all.Add($_, $second[$_])
    }
    catch {
        # catch the exception in order to carry on adding items
        # the effect will be that the values from $first will not be overwritten
        # just like with method 2
        Write-Warning $_.Exception.Message
    }
}
1 голос
/ 15 октября 2019

Я не понимаю вопроса? Вы можете добавить их.

$first = @{John = 'Doe'; Johnny = 'Doe'} # hashtables
$second = @{Jacky = 'Test'; Jack = 'Test'}
$all = $first + $second  # merge two hashtables
foreach ($i in $all.getenumerator()) { $i } # loops 4 times
1 голос
/ 14 октября 2019

Я думаю, что ваш $all_dict уже содержит то, что вы хотите (т.е. хеш-таблицу со всеми 4 записями), но ваш foreach( $dict in $all_dict ) не перечисляет записи хеш-таблицы, как вы ожидаете.

Быстрыйвместо этого нужно перебрать коллекцию Keys:

foreach( $key in $all.Keys )
{
   write-host $key
}

Более длинный ответ заключается в том, что в вашем примере PowerShell выполняет некоторые «вспомогательные» действия для вас с перечислением - foreach($key in $all) перечисляет только черезодин объект ($all), но write-host $all оценивает массив всех записей в $all и сериализует их в одну строку:

Сравните поведение этих двух строк, и вы можете увидетьразница:

PS> foreach($item in @{ "aaa"="bbb"; "ccc"="ddd" }) { write-host $item }
System.Collections.DictionaryEntry System.Collections.DictionaryEntry

PS> foreach($item in @{ "aaa"="bbb"; "ccc"="ddd" }.Keys) { write-host $item }
ccc
aaa

Кстати, следите за тем, не сталкиваются ли ваши ключи - например, если вы попробуете @{ "aaa"="bbb"; "ccc"="ddd" } + @{ "aaa"="eee" }, вы получите ошибку Item has already been added. Key in dictionary: 'aaa' Key being added: 'aaa'., так что вы можете захотеть найти лучшийспособ объединения ваших хеш-таблиц, а не просто +.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...