我正在将文件从Perl转换为PHP,但我需要帮助这一行:
@stuff_unique = grep !$list{$_}++, @stuff;
。
我知道stuff_unique
和stuff
是数组。
答案 0 :(得分:7)
这是一种常见的Perl习语,在perlfaq4
中有描述使用此结构,@stuff_unique
最终会得到@stuff
中至少看过一次的项目列表;换句话说,在没有重复的意义上,它只保留唯一的值。它的工作方式是:
Perl中的哈希就像一个具有唯一键的关联数组。 %list
就是这样的哈希。 $list{something}
是该哈希中名为“something”的元素。它的价值可以是你放在它里面的任何东西。
grep
遍历@stuff
中的项目。对于stuff
中的每个项目,该项目将用作%list
哈希中的哈希键。 ++
递增该对应哈希元素的值。因此,如果@stuff
包含“1,2,1”,则在第一次迭代时将创建名为“1”的哈希元素。它没有值,转换为布尔值false。前面的!
反转布尔意义。因此,在第一次迭代中,'1'哈希元素的false值被计算为true,因此该元素将传递给@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习惯一样扩展。
答案 1 :(得分:2)
使用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));