Вам не нужно проверять каждый уровень иерархии: вы можете просто выбрать значение, которое вам небезразлично. exists
не проверяет определенность, только если слот в хэше существует (он может существовать с неопределенным значением), поэтому, если вы заботитесь о том, что значение определено, вам нужно будет вызвать defined
, а не существовать. Если значение не определено, оно в логическом контексте оценивается как ложное, поэтому мы можем набрать немного меньше и уменьшить ваш пример до:
if ($Table{$key1}{$key2})
{
# do whatever
}
Однако, если значение в этом ключе определено, но имеет значение «false» (численно оценивается как ноль или является пустой строкой), это может привести к ложному отрицанию, поэтому мы должны явно проверить на определенность, если это возможно :
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, если указанный элемент в хеш-коде или массиве когда-либо был инициализирован, даже если соответствующее значение не определено. Элемент не будет автоматически восстановлен, если он не существует.
...
Элемент хеша или массива может быть истинным, только если он определен, и определен, если он существует, но обратное не всегда верно.