Как делает этот Perl grep, работают для определения объединения нескольких хешей?

Я не понимаю последнюю строку этой функции от Программирования Perl 3e.

Вот то, как Вы могли бы записать функцию, которая делает своего рода пересечение набора путем возврата списка ключей, происходящих во всех хешах, переданных ему:

@common = inter( \%foo, \%bar, \%joe );
sub inter {
    my %seen;
    for my $href (@_) {
        while (my $k = each %$href) {
            $seen{$k}++;
        }
    }
    return grep { $seen{$_} == @_ } keys %seen;
}

Я понимаю это %seen хеш, который отображает каждый ключ к количеству раз, с этим встретились в любом из хешей, предоставленных функции.

7
задан brian d foy 16 April 2010 в 04:07
поделиться

3 ответа

grep примет переданный ему список (в данном случае каждый элемент, видимый в любом из хэш-ссылок); и вернуть список только тех элементов, для которых выражение в блоке истинно (локально устанавливая переменную $ _ для каждого элемента в списке).

Давайте посмотрим, как вычисляется это выражение:

  • @_ - это массив всех параметров, переданных в подпрограмму - в нашем случае список переданных хеш-ссылок.

  • В $ seen {$ _} == @_ , этот список принудительно помещается в скалярный контекст (из-за == ).

  • При использовании в скалярном контексте список оценивается как количество элементов в списке - в приведенном выше примере вызова - до 3, поскольку было передано 3 хэш-ссылки.

Итак, для каждого ключа в % seen (например, каждый ключ замечен в любом из N хэшрефов); выражение $ seen {$ _} == @_ численно сравнивает количество раз, когда элемент был замечен в хешах, с общим количеством хешей - оно будет равно, конечно, только если элемент находится во ВСЕХ переданных хэшах и, следовательно, является членом нужного нам пересечения.

Итак, чтобы подвести итог анализа, grep вернет список всех ключей , которые встречаются в КАЖДОМ хэше (также встречаются N раз, где N - количество хешей). Например. перекресток.

16
ответ дан 6 December 2019 в 08:42
поделиться

Цель функции - найти элементы, которые появляются во всех переданных ей хэшах.

Последняя строка grep - это список, возвращенный из ключей% видимых . Чтобы определить, присутствует ли данный ключ во всех хэшах, переданных функции, мы можем сравнить значение этого ключа в % seen с количеством аргументов в inter .

В блоке grep , $ _ устанавливается для каждого элемента списка ключей и проверяется на предмет некоторых условий.

Массив в скалярном контексте оценивается по его длине. @_ - массив аргументов, переданных в подпрограмму. А оператор == помещает свои операнды в скалярный контекст, поэтому мы можем просто сравнить значение $ visible {$ _} с длиной @_ . Если они одинаковы, то этот ключ присутствует во всех хэшах.

2
ответ дан 6 December 2019 в 08:42
поделиться
grep block list 

Это применит блок к каждому элементу списка по очереди, элемент имеет псевдоним $ _. Если блок возвращает истину, элемент добавляется в возвращаемый массив.

в данном случае:

grep { $seen{$_} == @_ } keys %seen

Блок - это $ visible {$ _} == @_ , который сравнивает значение видимого хеша с @_ . @_ оценивается в скалярном контексте и, таким образом, возвращает количество элементов в массиве @_ . @_ представляет аргументы текущей функции. В этом случае (\% foo, \% bar, \% joe) , который возвращает 3 в скалярном контексте. Наш список - это keys% seen , который представляет собой массив, содержащий все ключи, присутствующие в % seen .

эквивалентные английские утверждения:

  • "дайте мне список всех ключей из % seen , где значение, связанное с этим ключом, равно числу из элементов, переданных этой функции "
  • ", дают мне список всех ключей из % замеченных , где значение, связанное с этим ключом is 3 "
  • " дайте мне список всех ключей из % замеченных , которые имеют значение 3 , то есть все ключи из % видимого , которые присутствуют в каждом из 3 хэш-адресов, переданных этой функции "
3
ответ дан 6 December 2019 в 08:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: