PowerShell Hash of hash of hash: Как их заполнить?

конечная ситуация должна выглядеть так:

   $BaseHash = @{
       "KEY_A" = @{
               "Hash2" = @{ "Txt"="descr"; "Val"=1.2;"End"=(get-date) }
               "Hash3" = @{ "Txt"="descr"; "Val"=1.2;"End"=(get-date) }
        }
       "KEY_B" = @{
               "Hash2" = @{ "Txt"="descr"; "Val"=1.2;"End"=(get-date) }
               "Hash3" = @{ "Txt"="descr"; "Val"=1.2;"End"=(get-date) }
        }
       "KEY_C" = @{
               "Hash2" = @{ "Txt"="descr"; "Val"=1.2;"End"=(get-date) }
               "Hash3" = @{ "Txt"="descr"; "Val"=1.2;"End"=(get-date) }
        }
   }

Но я начинаю с того, что все хэши были «пустыми»:

   $BaseHash = @{}

Хорошо, я попытался получить ошибку, но, похоже, это работает?:

    $key1 = "KEY_A"
    $key2 = "KEY_B"
    $Topic= "Hash1"
    $Topic2= "Hash2"
    $defHash  = @{ "Txt"="Descr.";"Val"=1.2;"end"=(get-date) }
    $empty    = @{}
    $BaseHash = @{}
    if ( !$BaseHash.ContainsKey($key1) ) { 
        $BaseHash.Add( $key1, $empty  )
        $BaseHash.$key1.Add( $Topic, $defHash )
        $BaseHash.$key1.Add( $Topic2, $defHash )
    }
    if ( !$BaseHash.ContainsKey($key2) ) { 
        $BaseHash.Add( $key2, $empty )
        $BaseHash.$key2.Add( $Topic, $defHash )
        $BaseHash.$key2.Add( $Topic2, $defHash )
    }
    #$BaseHash
    foreach ($h in $BaseHash.$key1.GetEnumerator() | select -ExpandProperty name) {
      if ( $BaseHash.$key1.$h.Val -ne 0.0 ) { 
        Write-Host "Found $key1  $h  $($BaseHash.$key1.$h.Val) $($BaseHash.$key1.$h.Txt)"
      }
    }
    foreach ($h in $BaseHash.$key2.GetEnumerator() | select -ExpandProperty name) {
      if ( $BaseHash.$key2.$h.Val -ne 0.0 ) { 
        Write-Host "Found $key2  $h  $($BaseHash.$key2.$h.Val) $($BaseHash.$key2.$h.Txt)"
      }
    }

Ошибка, которую я получаю, связана с добавлением Topic и Topic2 в key2-хеш:
Исключение при вызове Add with 2 Arguments: tЭлемент уже добавлен:

+ $BaseHash.$key2.Add <<<< ( $Topic, $defHash )<br>
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException<br>
+ FullyQualifiedErrorId : DotNetMethodException<br>

+ $BaseHash.$key2.Add <<<< ( $Topic2, $defHash )<br>
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException<br>
+ FullyQualifiedErrorId : DotNetMethodException<br>

С другой стороны все вроде бы добавилось:

Найдено KEY_A Hash2 1.2 Описание
Найдено KEY_A Hash1 1.2 Описание
Найдено KEY_B Hash2 1.2 Описание
Найдено KEY_B Hash1 1.2 Описание

1) Как избежать сообщения об ошибке?
2) Можете ли вы предложить лучший способ добавления хэшей или хэшей к хешу?

Заранее спасибо
Гули


person gooly    schedule 24.06.2014    source источник
comment
Что плохого в том, чтобы построить его, как предлагает ваш первый блок кода? Помимо отсутствующего @ перед первой фигурной скобкой и отсутствующего " после каждого Txt и перед =, он создает именно то, что вы хотите.   -  person TheMadTechnician    schedule 24.06.2014
comment
@ TheMadTechnician: Спасибо! Я только что исправил опечатки, но я все еще получаю сообщения об ошибках, когда я делаю $BaseHash.$key2.Add($Topic, $defHash) и $BaseHash.$key2.Add($Topic1, $defHash), как мне избавиться от их? В чем проблема? Полная (немецкая) ошибка: Исключение при вызове Add с 2 аргументами: tЭлемент уже добавлен...   -  person gooly    schedule 24.06.2014


Ответы (2)


Я нашел проблему. Проблема в том, что вы используете $empty как пустую хеш-таблицу, но затем используете ее в другой хэш-таблице и пытаетесь повторно использовать ее позже. В тот момент, когда вы Add( $key1, $empty ) установили эту хеш-таблицу в качестве значения. Когда вы вызываете $key1.Add(), вы выполняете метод .Add() вашей пустой хеш-таблицы $, добавляя в нее элементы. К тому времени, когда вы начнете что-либо делать с $key2, пустая хэш-таблица $ уже будет заполнена $topic и $topic2, поэтому при попытке добавить их снова вы получите сообщение об ошибке.

Вместо этого просто выполните $BaseHash.Add( $Key1, @{} ) и идите оттуда.

person TheMadTechnician    schedule 24.06.2014
comment
Не будьте робкими с PowerShell, удача сопутствует смелым. Честно говоря, вы слишком усложняете весь процесс, начиная с пустых хеш-таблиц и добавляя данные постфактум. Но если это работает для вас, тогда используйте то, что работает. - person TheMadTechnician; 24.06.2014

Как насчет чего-то вроде:

$BaseHash = @{}

$key1 = "KEY_A"
$key2 = "KEY_B"
$Topic= "Hash1"
$Topic2= "Hash2"
$defHash  = @{ "Txt"="Descr.";"Val"=1.2;"end"=(get-date) }

if( -not $BaseHash.ContainsKey( $key1 )) {
    $BaseHash[$key1] = [ordered]@{}
    $BaseHash[$key1][$Topic] += $defHash
    $BaseHash[$key1][$Topic2] += $defHash
}

if( -not $BaseHash.ContainsKey( $key2 )) {
    $BaseHash[$key2] = [ordered]@{}
    $BaseHash[$key2][$Topic] += $defHash
    $BaseHash[$key2][$Topic2] += $defHash
}

foreach ($h in $BaseHash.$key1.GetEnumerator() | select -ExpandProperty name) {
      if ( $BaseHash.$key1.$h.Val -ne 0.0 ) { 
        Write-Host "Found $key1  $h  $($BaseHash.$key1.$h.Val) $($BaseHash.$key1.$h.Txt)"
      }
    }
    foreach ($h in $BaseHash.$key2.GetEnumerator() | select -ExpandProperty name) {
      if ( $BaseHash.$key2.$h.Val -ne 0.0 ) { 
        Write-Host "Found $key2  $h  $($BaseHash.$key2.$h.Val) $($BaseHash.$key2.$h.Txt)"
      }
    }
person Hunter Eidson    schedule 24.06.2014
comment
Спасибо - я пытался, но все равно получаю ту же ошибку: Ошибка в +=-Opretator: элемент уже добавлен. Ключ в словаре (? ориг. 'Wörterbuch') конец... - person gooly; 24.06.2014