Вам не нужно проверять каждый уровень иерархии: вы можете просто перейти к интересующему вас значению. exists
не проверяет определенность, только если слот в хэше существует (он может существовать с неопределенным значением), поэтому, если вам важно, чтобы значение было определено, вам нужно будет вызвать defined
, а не существует. Если значение не определено, оно оценивается в логическом контексте как false, поэтому мы можем ввести немного меньше и сократить ваш пример до:
if ($Table{$key1}{$key2})
{
# do whatever
}
Однако, если значение в этом ключе определено, но является «ложным» (численно оценивается как ноль или является пустой строкой), это может привести к ложному отрицательному результату, поэтому мы должны явно проверить определенность, если это возможно:
if (defined $Table{$key1}{$key2})
{
# do whatever
}
Если вы не хотите автоматически оживлять $Table{$key1}
, вы можете сначала проверить его существование, что приводит нас к "лучшему" способу для общего случая:
if (exists $Table{$key1} and defined $Table{$key1}{$key2})
{
# do whatever
}
Если вы собираетесь делать это много для различных полей в хэше, вы можете добавить некоторые методы доступа в стиле OO, которые сделают эту работу за вас:
sub has_field
{
my ($this, $fieldName) = @_;
return exists $this->{data} && defined $this->{data}{$fieldName});
}
Я уверен, что вы уже читали его, но не помешает еще раз прочитать соответствующую документацию:
Учитывая выражение, задающее элемент хеша или элемент массива, exists
возвращает значение true, если указанный элемент в хеше или массиве когда-либо был инициализирован, даже если соответствующее значение не определено. Элемент не оживляется автоматически, если он не существует.
...
Элемент хеша или массива может быть истинным, только если он определен, и определен, если он существует, но обратное не обязательно верно.
person
Ether
schedule
27.04.2010