2014-11-06 78 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