Я переводю файл с Perl на PHP, но мне нужна помощь с этой строкой:
@stuff_unique = grep !$list{$_}++, @stuff;
,
я знаю stuff_unique
а также stuff
являются массивами.
Это распространенная идиома Perl, описанная в perlfaq4
С этой конструкцией @stuff_unique
в конечном итоге список предметов, которые были замечены по крайней мере один раз в @stuff
; другими словами, в нем остаются только уникальные значения, в том смысле, что повторов не будет. Вот как это работает:
Хэш в Perl похож на ассоциативный массив с уникальными ключами. %list
такой хэш $list{something}
является элементом в этом хэше с именем «что-то». Его ценность может быть любой, что вы вкладываете в нее.
grep
перебирает элементы в @stuff
, Для каждого элемента в stuff
этот элемент используется в качестве хеш-ключа в %list
хэш. ++
увеличивает значение для этого соответствующего хеш-элемента. Так что если @stuff
содержит «1, 2, 1», тогда на первой итерации будет создан хеш-элемент с именем «1». Он не имеет значения, что переводится как логическое значение false. !
впереди меняет булево значение. Таким образом, на этой первой итерации ложное значение для хеш-элемента ‘1’ оценивается как истинное, поэтому этот элемент проходит через @stuff_unique
, Наконец, выполняется постинкремент, поэтому значение, хранящееся в 1
элемент хеша увеличивается до 1.
На втором элементе, 2 также еще не был замечен, поэтому он проходит, и его соответствующий хэш-элемент также увеличивается до 1.
На третьей итерации снова появляется «1». $list{1}
уже равен 1
, который является истинным значением. ! истинно ложно; так что этот не проходит через @stuff_unique
,
Один за другим элементы в @stuff
будет проверен таким образом; обнаружение, если они были замечены ранее, и если они не видели, они проходят через @stuff_unique
,
PHP предоставляет функцию под названием array_unique, который должен сделать то же самое для вас. Это будет использовано так:
$stuff_unique = array_unique($stuff);
К счастью для Perl, это линейная операция. К сожалению для людей PHP, это реализовано внутри, сортируя входной массив, а затем перебирая его, пропуская дубликаты по пути. Это означает, что это O(n + n log n)
операция (упрощенная до O(n log n)
), то есть его реализация не может масштабироваться так же, как обычная идиома Perl.
Радость использования php замыканий,
<?php
$stuff = array(1,1,2,2,2,3,3,3);
$list = array();
$stuff_unique = array_filter($stuff, function($_) use (&$list) {
return !$list[$_]++;
});
print_r(array_values($stuff_unique));
или же
<?php
$stuff = array(1,1,2,2,2,3,3,3);
$stuff_unique = array_keys(array_flip($stuff));
print_r($stuff_unique);
или же
$stuff_unique = array_values(array_unique($stuff));