Как проверить, существует ли значение в хэше? - PullRequest
10 голосов
/ 15 января 2011

Допустим, у меня есть это

#!/usr/bin/perl

%x = ('a' => 1, 'b' => 2, 'c' => 3);

, и я хотел бы знать, является ли значение 2 хеш-значением в %x.

Как это делается?

Ответы [ 6 ]

17 голосов
/ 15 января 2011

По сути, хеш - это структура данных, оптимизированная для решения обратного вопроса, зная, присутствует ли ключ 2.Но сложно судить, не зная, поэтому предположим, что это не изменится.

Представленные здесь возможности будут зависеть от:

  • как часто вам нужно это делать
  • насколько динамичен хеш

Однократная операция

  • grep $_==2, values %x (также пишется grep {$_==1} values %x) вернет список из двух чисел, имеющихся в наличиив хэше или, в скалярном контексте, количество совпадений.Оценивается как логическое значение в условии, оно дает именно то, что вы хотите.
    grep работает на тех версиях Perl, сколько я помню.
  • use List::Util qw(first); first {$_==2} values %x возвращает толькопервый матч, undef, если нет.Это делает его более быстрым, так как оно замкнет накоротко (остановит проверку элементов), как только это будет успешно выполнено.Это не проблема для 2, но позаботьтесь о том, чтобы возвращаемый элемент не обязательно оценивался как логическое true.Используйте defined в этих случаях.
    List::Util является частью ядра Perl, так как 5.8.
  • use List::MoreUtils qw(any); any {$_==2} values %x возвращает именно ту информацию, которую вы запрашивали как логическое значение, идемонстрирует поведение короткого замыкания.
    List::MoreUtils доступно из CPAN.
  • 2 ~~ [values %x] возвращает именно ту информацию, которую вы запрашивали как логическое значение, и демонстрирует поведение короткого замыкания.
    Интеллектуальное сопоставление доступно в Perl с 5.10.

Повторные операции, статический хэш

Создайте хэш, который сопоставляет значения с ключами, и используйтеэтот как естественный хеш для проверки существования ключа.

my %r = reverse %x;
if ( exists $r{2} ) { ... }

Повторный операционный, динамический хеш

Используйте обратный поиск, как указано выше.Вам нужно будет поддерживать его в актуальном состоянии, что оставлено в качестве упражнения для читателя / редактора.(подсказка: столкновение значений сложно)

10 голосов
/ 15 января 2011

Более короткий ответ с использованием умного соответствия (Perl версии 5.10 или более поздней):

print 2 ~~ [values %x];
8 голосов
/ 15 января 2011
my %reverse = reverse %x;
if( defined( $reverse{2} ) ) {
  print "2 is a value in the hash!\n";
}

Если вы хотите узнать ключи, для которых значение равно 2:

foreach my $key ( keys %x ) {
  print "2 is the value for $key\n" if $x{$key} == 2;
}
7 голосов
/ 15 января 2011

Ответ каждого до сих пор не зависел от производительности. В то время как решение Smart-Match (~~) короткое замыкание (например, прекращает поиск, когда что-то найдено), grep не делает.

Следовательно, вот решение, которое может иметь лучшую производительность для Perl до 5.10, без оператора умного сопоставления:

use List::MoreUtils qw(any);
if (any { $_ == 2 } values %x) {
    print "Found!\n";
}

Обратите внимание, что в данном случае это всего лишь конкретный пример поиска в списке (values %x), и поэтому, если вас интересует производительность, стандартный анализ производительности поиска в списке применяется как , как обсуждалось подробно в этом ответе

5 голосов
/ 15 января 2011

grep и значения

my %x = ('a' => 1, 'b' => 2, 'c' => 3); 

if (grep { $_ == 2 } values %x ) {
    print "2 is in hash\n";
}
else {
    print "2 is not in hash\n";
}

Смотри также: perldoc -q hash

3 голосов
/ 15 января 2011

Где $ count будет результатом:

my $count = grep { $_ == 2 } values %x;

Это покажет вам не только значение в хэше, но и сколько раз оно встречается как значение.Также вы можете сделать это так:

my $count = grep {/2/} values %x;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...