这里有一种方法:
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'对于更大的列表也可能有严重的性能问题,请参阅我的评论和指向编辑中相关的过去讨论的链接。 –