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

95

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

$hash1{'1'} = 'red';
$hash1{'2'} = 'blue';
$hash2{'3'} = 'green';
$hash2{'4'} = 'yellow';
Млейкамп
источник

Ответы:

168

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

    % hash1 = (% hash1,% hash2)

    ## или иначе ...

    @ hash1 {ключи% hash2} = значения% hash2;

    ## или со ссылками ...

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

Обзор

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

Решение

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

Ловушки

Смотрите также


Сноски

1 * (он же ассоциативный массив , он же словарь )

Dreftymac
источник
2
Да, если нет конфликтов ключей, @ hash1 {keys% hash2} = values% hash2; это самый быстрый и короткий путь, AFAIK.
kixx
46
почему ты не можешь просто сделать%hash1 = (%hash1, %hash2)
user102008
1
Кажется, он работает и со ссылками: $ hash_ref1 = ($ hash_ref1, $ hash_ref2);
Леп
2
Будет установлено $hash_ref1значение $hash_ref2, без слияния. Хочешь $hash_ref1 = { %$hash_ref1, %$hash_ref2 };, я подредактирую ответ.
M Somerville
38

Посмотрите 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;
Брайан Д Фой
источник
Приятно сослаться на perlfaq и другие ресурсы в другом вопросе
Крис,
14

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

LeeGee
источник
получивший наибольшее количество голосов ответ был обновлен, чтобы включить это.
dreftymac
6

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

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

а не предложенный выше ответ с использованием скобок:

$hash_ref1 = ($hash_ref1, $hash_ref2);
JeanieJ
источник