這裏有一種方法:
DeleteDuplicates[list, [email protected]#1 === [email protected]#2 &]
編輯
注意,定時和以下討論是基於M7
在反射一點,我發現這將是(至少)量級大型列表更快的溶液,和幅度有時兩個數量速度更快,對於這種特殊情況下(可能是更好的方法把它就是下面的解決方案將有不同的計算複雜性):
Clear[delDupBy];
delDupBy[nested_List, n_Integer] :=
Module[{parts = nested[[All, n]], ord, unpos},
ord = Ordering[parts];
unpos = [email protected]@Prepend[Map[Length, [email protected][[ord]]], 1];
nested[[[email protected][[unpos]]]]];
基準:
In[406]:=
largeList = RandomInteger[{1,15},{50000,2}];
In[407]:= delDupBy[largeList,1]//Timing
Out[407]= {0.016,{{13,4},{12,1},{1,6},{6,13},{10,12},{7,15},{8,14},
{14,4},{4,1},{11,9},{5,11},{15,4},{2,7},{3,2},{9,12}}}
In[408]:= DeleteDuplicates[largeList,[email protected]#[email protected]#2&]//Timing
Out[408]= {1.265,{{13,4},{12,1},{1,6},{6,13},{10,12},{7,15},{8,14},{14,4},
{4,1},{11,9},{5,11},{15,4},{2,7},{3,2},{9,12}}}
這是特別顯着的,因爲DeleteDuplicates
是一個內置函數。我可以做一個盲目的猜測DeleteDuplicates
與用戶定義的測試使用二次時間兩兩比較的算法,而delDupBy
是在列表的大小n*log n
。
我認爲這是一個重要的教訓:使用自定義測試時,應該注意內置函數,如Union
,Sort
,DeleteDuplicates
等。我在this Mathgroup線程中進行了更廣泛的討論,其中還有其他有洞察力的回覆。
最後,讓我提,here之前,正是這種問題已經被問(與強調效率)。我將在這裏重現一個解決方案,我給的情況下,當第一(或者,通常,n
個)元素是正整數(推廣到任意整數很簡單):
Clear[sparseArrayElements];
sparseArrayElements[HoldPattern[SparseArray[u___]]] := {u}[[4, 3]]
Clear[deleteDuplicatesBy];
Options[deleteDuplicatesBy] = {Ordered -> True, Threshold -> 1000000};
deleteDuplicatesBy[data_List, n_Integer, opts___?OptionQ] :=
Module[{fdata = data[[All, n]], parr,
rlen = Range[Length[data], 1, -1],
preserveOrder = Ordered /. Flatten[{opts}] /. Options[deleteDuplicatesBy],
threshold = Threshold /. Flatten[{opts}] /. Options[deleteDuplicatesBy], dim},
dim = Max[fdata];
parr = If[dim < threshold, Table[0, {dim}], SparseArray[{}, dim, 0]];
parr[[fdata[[rlen]]]] = rlen;
parr = [email protected][dim < threshold, [email protected], parr];
data[[If[preserveOrder, [email protected], parr]]]
];
其工作原理是使用第一個(或通常爲n
)元素作爲我們預先分配的某個 巨大表中的位置,利用它們是正整數)。在某些情況下,這個可以給我們帶來瘋狂的表現。觀察:
In[423]:= hugeList = RandomInteger[{1,1000},{500000,2}];
In[424]:= delDupBy[hugeList,1]//Short//Timing
Out[424]= {0.219,{{153,549},{887,328},{731,825},<<994>>,{986,150},{92,581},{988,147}}}
In[430]:= deleteDuplicatesBy[hugeList,1]//Short//Timing
Out[430]= {0.032,{{153,549},{887,328},{731,825},<<994>>,{986,150},{92,581},{988,147}}}
哇,太棒了!我不知道這些標準可以應用於「整個」列表,我認爲它只適用於迭代時的特定「元素」。學到了新東西。謝謝 – Nasser
也許在某些情況下'Union'和'SameTest'可能有用?例如'Union [{{1,3},{1,2},{4,5}},SameTest - >(First @#1 == First @#2&)]'。不過,我更喜歡獅子座的方法。 – tomd
@TomD'Union' with'SameTest'對於更大的列表也可能有嚴重的性能問題,請參閱我的評論和指向編輯中相關的過去討論的鏈接。 –