2014-11-06 57 views
4

我正在将文件从Perl转换为PHP,但我需要此行的帮助:
@stuff_unique = grep !$list{$_}++, @stuff;。我知道stuff_uniquestuff是数组。将Perl的一行转换为PHP

+1

它是找到阵列'@ stuff'的所有唯一线和将其存​​储在'@ stuff_unique'中(删除重复项)。 – chilemagic 2014-11-06 16:12:36

回答

7

这是一种常见的Perl成语,在perlfaq4

描述用该构建体,@stuff_unique将结束与在@stuff被视为至少一次的项目的列表;换句话说,它只剩下唯一的价值,就是说不会有重复。它的工作方式是这样的:

Perl中的散列就像一个具有唯一键的关联数组。 %list就是这样一个散列。 $list{something}是名为“something”的哈希中的一个元素。它的价值可以是任何你在其中放置的东西。

grep遍历@stuff中的项目。对于stuff中的每个项目,该项目在%list散列中用作散列键。 ++递增该相应散列元素的值。因此,如果@stuff包含“1,2,1”,那么在第一次迭代中将创建名为“1”的哈希元素。它没有价值,这转化为布尔假。前面的!颠倒了布尔意义。因此,在第一次迭代中,'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成语那样扩展。

+0

是的,谢谢。虽然不能赞成答案。 – Olsi 2014-11-06 16:25:29

+0

@Olsi有什么我必须添加或澄清的答案是值得大拇指,和/或“接受”复选标记? – DavidO 2014-11-06 16:28:50

+0

@DavidO OP在首次发布问题时没有足够的代表。 – 2014-11-06 16:34:22

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)); 
+1

我喜欢这个,因为它是Perl语言的更直接的翻译,可能具有类似的时间复杂性特征。 +1。 – DavidO 2014-11-06 16:37:01

+0

@DavidO是的,但是在php中是PITA。我猜'foreach'表现要好得多,并且对PHP社区更为熟悉。 – 2014-11-06 16:40:21

+0

对于第一句话,如果有人有一定的期望,当他们证明属实时,他不会失望。 ;) – DavidO 2014-11-06 16:42:08