Как я могу объединить хэши в Perl?

87

Каков наилучший способ объединить оба хэша в% hash1? Я всегда знаю, что% hash2 и% hash1 всегда имеют уникальные ключи. Я также предпочел бы одну строку кода, если это возможно.

$hash1{'1'} = 'red';
$hash1{'2'} = 'blue';
$hash2{'3'} = 'green';
$hash2{'4'} = 'yellow';
Теги:
dictionary
merge
hash

4 ответа

148
Лучший ответ

Быстрый ответ (TL; DR)


    %newHash = (%hash1, %hash2); %hash1 = %newHash;

    ## or else ...

    @hash1{keys %hash2} = values %hash2;

    ## or else ...

    %hash1 = (%hash1, %hash2)

    ## or with references ... (per https://stackoverflow.com/users/196507/lepe)

    $hash_ref1 = ($hash_ref1, $hash_ref2);

Обзор

  • Контекст: Perl 5.x
  • Проблема: Пользователь хочет объединить две хэши 1 в одну переменную

Решение

  • используйте синтаксис выше для простых переменных
  • использовать Hash:: Merge для сложных вложенных переменных

Ловушки

  • Что делать, когда оба хэша содержат один или несколько дубликатов ключей
    • Если пара ключ-значение с пустым значением когда-либо перезаписывает пару ключ-значение с непустым значением?
    • Что представляет собой пустое и непустое значение в первую очередь? (например, undef, пустая строка, false, ложь...)
    • (Примечание: исходный вопрос исключает этот сценарий, но это важно рассмотреть)

См. также


Сноски

1 * (aka associative-array, aka dictionary)

  • 2
    Да, если нет столкновений ключей, @ hash1 {keys% hash2} = values% hash2; самый быстрый и короткий путь, AFAIK.
  • 44
    почему вы не можете просто сделать %hash1 = (%hash1, %hash2)
Показать ещё 4 комментария
37

Отъезд perlfaq4: Как объединить два хэша. В документации Perl есть много хорошей информации, и вы можете получить ее сразу, а не ждать, пока кто-то еще ответит на нее.:)


Прежде чем вы решите объединить два хэша, вы должны решить, что делать, если оба хэша содержат ключи, которые являются одинаковыми, и если вы хотите оставить исходные хеши как они есть.

Если вы хотите сохранить исходные хэши, скопируйте один хэш (% hash1) в новый хеш (% new_hash), затем добавьте ключи из другого хеша (% hash2 в новый хеш. Проверка того, что ключ уже существует в% new_hash дает вам возможность решить, что делать с дубликатами:

my %new_hash = %hash1; # make a copy; leave %hash1 alone

foreach my $key2 ( keys %hash2 )
    {
    if( exists $new_hash{$key2} )
        {
        warn "Key [$key2] is in both hashes!";
        # handle the duplicate (perhaps only warning)
        ...
        next;
        }
    else
        {
        $new_hash{$key2} = $hash2{$key2};
        }
    }

Если вы не хотите создавать новый хеш, вы все равно можете использовать эту технику цикла; просто измените% new_hash на% hash1.

foreach my $key2 ( keys %hash2 )
    {
    if( exists $hash1{$key2} )
        {
        warn "Key [$key2] is in both hashes!";
        # handle the duplicate (perhaps only warning)
        ...
        next;
        }
    else
        {
        $hash1{$key2} = $hash2{$key2};
        }
    }

Если вам все равно, что один хэш перезаписывает ключи и значения из другого, вы можете просто использовать хэш-фрагмент, чтобы добавить один хэш к другому. В этом случае значения из% hash2 заменяют значения из% hash1, когда они имеют общие ключи:

@hash1{ keys %hash2 } = values %hash2;
  • 0
    приятно ссылаться на perlfaq и другие ресурсы в другом вопросе
12

Это старый вопрос, но он очень высок в моем поиске в Google для "хэшей слияния perl" - и все же он не упоминает очень полезный модуль CPAN Hash:: Merge

  • 0
    обновленный ответ был обновлен, чтобы включить это.
3

Для хеш-ссылок. Вы должны использовать фигурные скобки

$hash_ref1 = {%$hash_ref1, %$hash_ref2};

вместо предлагаемого ответа выше, используя скобки

$hash_ref1 = ($hash_ref1, $hash_ref2);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню