在Mathematica中显示重复项

Mar*_*zek 12 wolfram-mathematica list duplicates

在Mathematica我有一个列表:

x = {1,2,3,3,4,5,5,6}
Run Code Online (Sandbox Code Playgroud)

如何制作包含重复项的列表?喜欢:

{3,5}
Run Code Online (Sandbox Code Playgroud)

我一直在将Lists视为集合,如果列表中有Except []之类的内容,那么我可以这样做:

unique = Union[x]
duplicates = MyExcept[x,unique]
Run Code Online (Sandbox Code Playgroud)

(当然,如果X将具有两个以上的重复-说,{1,2,2,2,3,4,4-},存在输出将是{2,2,4},但附加的联盟[]会解决这个问题.)

但是没有那样的东西(如果我确实理解了那里的所有功能).

那么,该怎么做?

Wil*_*son 11

有很多方法可以像这样进行列表提取; 这是我想到的第一件事:

Part[Select[Tally@x, Part[#, 2] > 1 &], All, 1]

或者,更可读的部分:

Tally@x
Select[%, Part[#, 2] > 1 &]
Part[%, All, 1]

它分别给出

{{1, 1}, {2, 1}, {3, 2}, {4, 1}, {5, 2}, {6, 1}}
{{3, 2}, {5, 2}}
{3, 5}

也许你可以想到更有效(在时间或代码空间)的方式 :)

顺便说一句,如果列表未排序,那么您需要先运行Sort它才能运行.


dre*_*ves 6

这是一种通过列表单次传递的方法:

collectDups[l_] := Block[{i}, i[n_]:= (i[n] = n; Unevaluated@Sequence[]); i /@ l]
Run Code Online (Sandbox Code Playgroud)

例如:

collectDups[{1, 1, 6, 1, 3, 4, 4, 5, 4, 4, 2, 2}] --> {1, 1, 4, 4, 4, 2}
Run Code Online (Sandbox Code Playgroud)

如果你想要唯一重复的列表 - {1, 4, 2}- 然后将上面的内容包装起来DeleteDuplicates,这是另一个单一的遍历列表(Union效率较低,因为它也会对结果进行排序).

collectDups[l_] := 
  DeleteDuplicates@Block[{i}, i[n_]:= (i[n] = n; Unevaluated@Sequence[]); i /@ l]
Run Code Online (Sandbox Code Playgroud)

Will Robertson的解决方案可能更好,因为它更直接,但我认为如果你想要更快速地获得更多,那么这应该会赢.但如果你关心这一点,你就不会在Mathematica中编程!:)


Mr.*_*ard 5

以下是Tally方法的几种更快的变体.

f4 使用Carl Woll和Oliver Ruebenkoenig在MathGroup上给出的"技巧".

f2 = Tally@# /. {{_, 1} :> Sequence[], {a_, _} :> a} &;

f3 = Pick[#, Unitize[#2 - 1], 1] & @@ Transpose@Tally@# &;

f4 = # ~Extract~ SparseArray[Unitize[#2 - 1]]["NonzeroPositions"] & @@ Transpose@Tally@# &;
Run Code Online (Sandbox Code Playgroud)

速度比较(f1包括参考)

a = RandomInteger[100000, 25000];

f1 = Part[Select[Tally@#, Part[#, 2] > 1 &], All, 1] &;

First@Timing@Do[#@a, {50}] & /@ {f1, f2, f3, f4, Tally}

SameQ @@ (#@a &) /@ {f1, f2, f3, f4}

Out[]= {3.188, 1.296, 0.719, 0.375, 0.36}

Out[]= True
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,f4相对于纯粹的几乎没有开销Tally!