Как выполнить поиск многозначного имени в хеш-таблице?

#powershell

#powershell

Вопрос:

Если у меня есть хеш-таблица с многозначным именем, как мне указать имя при выполнении поиска?

Вот несколько надуманных примеров…

 $unary = @{
    $false, "!A";
    $true,  "A"
}

$unary
Name                           Value
----                           -----
False                          !A
True                           A

$unary[$false]
!A
$unary[$true]
A
  

Пока все хорошо.

 $binary = @{
  ($false, $false) = "!A and !B"
  ($false, $true)  = "!A and B"
  ($true,  $false) = "A and !B"
  ($true,  $true)  = "A and B"
}

$binary
Name                           Value
----                           -----
{False, True}                  !A and B
{True, False}                  A and !B
{True, True}                   A and B
{False, False}                 !A and !B

$binary[$false, $true]
//Nothing
$binary[($false, $true)]
//Nothing
$binary[{$false, $true}]
//Nothing
//www.stackoverflow.com... :)
  

Что мне нужно указать в $binary[...] , чтобы получить значение?

Комментарии:

1. Ни в коем случае! Забудьте об этом! Это работало бы на других языках (например, на Ruby works), а не на posh.

Ответ №1:

Ваша проблема в том, что вы используете массивы в качестве ключей в хеш-таблице. Просто чтобы проиллюстрировать, что здесь пошло не так:

 PS Home:> $x=$false,$false
PS Home:> $y=@($binary.Keys)[0]
PS Home:> $x
False
False
PS Home:> $y
False
False
PS Home:> $x.Equals($y)
False
  

Оба объекта также имеют разные хэш-коды. Их никогда не будет хорошей идеей использовать в качестве ключей в хеш-таблицах, поскольку вы не сможете извлечь значения снова, если не будете использовать точно такие же ссылки, которые вы поместили в хеш-таблицу.

Вероятно, проще было бы использовать один объект в качестве ключа:

 $binary = @{
  0 = "!A and !B"
  1  = "!A and B"
  10 = "A and !B"
  11  = "A and B"
}
  

или что-то подобное. Затем извлекая

 $binary[01]
  

даст результат "!A and B" , как и ожидалось.

Обратите также внимание, что Список будет иметь ту же проблему с равенством. Кортежи могут работать, но они недоступны в .NET 2.

Комментарии:

1. Спасибо за объяснение, почему это не работает. Я выбрал комбинацию вашего ответа (укажите ключ с одним значением) и ответа мьолинора (сделайте комбинированный ключ строкой).

Ответ №2:

Это не самое лучшее решение, но в зависимости от того, что вы хотите сделать, оно может помочь.

 $unary = new-objectobject[]’ 2
$unary[$false] = "!A"
$unary[$true] = "A"

$binary= new-objectobject[,]’ 2,2
$binary[$false,$false] = "!A and !B"
$binary[$false,$true] = "!A and B"
$binary[$true,$false] = "A and !B"
$binary[$true,$true] = "A and B"
  

Результат :

 PS > $binary[$true,$true]
A and B
  

Ответ №3:

Возможно, это не то, что вы хотели увидеть, но:

 $binary = @{
  [string]($false,$true)  = "!A and B"
  [string]($true,$false) = "A and !B"
  [string]($true,$true)  = "A and B"
}

$binary[[string]($false,$true)]


!A and B
  

Комментарии:

1. "$($false,$true)" был бы более короткий способ сделать это. Или просто "False True" 🙂

2. Это короче. В любом случае, это в основном тот же ответ, что и тот, который вы опубликовали, а именно: свести ключи к скаляру.

3. Действительно. Хотя это неуловимо. И требует небольшого знания .NET. Если вы пришли в PowerShell с C #, это, вероятно, довольно очевидно, но в остальном …

4. Спасибо, преобразование моих многозначных ключей в строку было простым изменением того, что у меня уже было, и это просто сработало.