Проверка на наличие хеш-ключа создает ключ - PullRequest
6 голосов
/ 20 марта 2012

С учетом следующего кода

#!/usr/bin/perl

use Data::Dumper;

my %hash;
my @colos = qw(ac4 ch1 ir2 ird kr3);

foreach my $colo (@colos) {
    if(exists $hash{output}{$colo}) {
        print "$colo is in the hash\n";
    }
}

print Dumper(\%hash);

У меня есть пустой хеш, который создан. У меня есть массив с несколькими сокращениями в нем. Если я перебираю массив, чтобы посмотреть, есть ли эти парни в хэше, в STDOUT ничего не отображается, что ожидается, но $ hash {output} по какой-то причине создан. Это не имеет смысла. Все, что я делаю, это если существует. Где я ошибся?

Ответы [ 4 ]

7 голосов
/ 20 марта 2012

exists ищет элемент хеша в данном хеше. Ваш код автоматически генерирует хэш
%{ $hash{output} } и проверку, существует ли в этом хеше элемент хэша с ключом $colo.

Попробуйте следующее:

if(exists $hash{output}{$colo}) {

изменено на

if(exists $hash{output} and exists $hash{output}{$colo}) {

Конечно, вы можете написать подпрограмму, которая скрывает эту сложность от вашего кода.

3 голосов
/ 20 марта 2012

У вас уже есть пара хороших ответов, но, если вы хотите больше узнать об этом поведении, его обычно называют «автовивификацией», и есть модуль CPAN , который можно отключить, если вы захотите.предпочитаю, чтобы этого не случилось.

3 голосов
/ 20 марта 2012

Perl создает его, потому что exists проверяет последний указанный ключ, он не проверяет рекурсивно.Он не должен создаваться, если вы вместо этого выполните:

if( exists $hash{output} && exists $hash{output}{$colo} ) {

Однако зачем вам вообще нужен дополнительный ключ?Почему не просто $hash{$colo}?Также, если вы Если вы use strict, вы получите предупреждение о неинициализированном значении в $hash.

1 голос
/ 20 марта 2012

Фактический код / ​​хэш более сложен.Хеш имеет вид: $ revolution_hash {output} {oor} {$ colo} {$ type} {$ hostname} {file} {$ filename} =

Как уже говорили другие, когда вы спрашиваете о существовании $foo{bar}{fubar}, Perl автоматически создает $foo{bar}, чтобы проверить, существует ли $foo{bar}{fubar}.Если вы хотите предотвратить это, вы должны проверить, существует ли $foo{bar}, и если да, то проверить, существует ли $foo{bar}{fubar}.

Однако, что привлекло мое внимание, был ваш семислойный хэш.Когда ваши структуры данных начинают становиться такими сложными, вы действительно должны использовать Perl Object Oriented Coding.Я знаю, что многие напуганы ориентированным на Perl программированием, но Perl, вероятно, является одним из самых простых языков для людей при получении ООП.

Если ни для чего иного, вы используете ООП по той же причине, что и вы.используйте use strict;.Когда я use strict;, Perl легко подхватит, где я использовал $foobar в качестве переменной в одном месте, но затем назову его $fubar в другом месте.Вы теряете эту защиту со сложными структурами данных.Например, вы можете поместить $rotation_hash{output}{oor} в одном месте, но $rotation_hash{oor}{output} в другом месте, и use strict этого не поймет.Но если вы объявляете объекты с помощью package и используете подпрограммы в качестве методов и конструкторов, вы получаете это обратно.

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

В документацию по Perl включены некоторые отличные учебные пособия .Если вы не знакомы с ООП Perl, вам следует пройти уроки и попробовать.

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