# Select a repeated element in a list

I want to select all elements that repeat 4 times in the list. I propose this code

list = {a, a, a, b, c, a, b, b, b, e};

elementsplus4 = Select[list, Count[list, #] == 4 &];


I obtain:

{a, a, a, b, a, b, b, b}


How can I obtain just {a,b}

• DeleteDuplicates – Ajasja Jan 13 '14 at 7:08
• Cases[Tally[list], {i_, 4}:>i] – Rojo Jan 13 '14 at 7:09

You may use Tally to finish the task as follows:

Cases[Tally[list], {x_, 4} :> x]


the result will be {a,b}.

• Yup, that's the one. +1 – Mr.Wizard Jan 13 '14 at 7:18
• Cases[Tally[list], {x_, 4} -> x] seems to work too. – DumpsterDoofus Jan 28 '14 at 16:06

The code given by Rojo and sunt05 is almost surely the cleanest:

Cases[Tally @ list, {x_, 4} :> x]


However, here are some other possibilities:

Cases[Split @ Sort @ list, {x_, _, _, _} :> x]

Cases[Split @ Sort @ list, {Repeated[x_, {4}]} :> x]

Cases[Last @ Reap[Sow[1, list], _, {#, Tr@#2} &], {x_, 4} :> x]

Module[{c},
c[_] = 0;
Scan[c[#]++ &, list];
Cases[DownValues[c], (_@_@x_ :> 4) :> x]
]


## Performance

Interestingly, some of these may be significantly faster than Tally in certain cases:

list = FromCharacterCode /@ RandomInteger[15000, 100000];

Cases[Tally @ list, {x_, 4} :> x]                               // Timing // First

Cases[Last @ Reap[Sow[1, list], _, {#, Tr@#2} &], {x_, 4} :> x] // Timing // First

Module[{c},
c[_] = 0;
Scan[c[#]++ &, list];
Cases[DownValues[c], (_@_@x_ :> 4) :> x]
] // Timing // First

0.546

0.109

0.2622


Since it seems to be only in the case of String objects that Sow/Reap is faster, for clarity one might write the second method as:

stringTally = Last @ Reap[Sow[1, #], _, {#, Tr@#2} &] &;

Cases[stringTally @ list, {x_, 4} :> x] // Timing // First

0.103


The OP wrote: "I want to list all elements that appear at least four times." In light of that here are all the methods modified accordingly:

stringTally = Last @ Reap[Sow[1, #], _, {#, Tr@#2} &] &;

Cases[stringTally @ list, {x_, n_} /; n >= 4 :> x]

Cases[Split @ Sort @ list, {x_, _, _, __} :> x]

Cases[Split @ Sort @ list, {Repeated[x_, {4, ∞}]} :> x]

Cases[Last @ Reap[Sow[1, list], _, {#, Tr@#2} &], {x_, n_} /; n >= 4 :> x]

Module[{c},
c[_] = 0;
Scan[c[#]++ &, list];
Cases[DownValues[c], (_@_@x_ :> n_) /; n >= 4 :> x]
]

• How can we change Cases[Last @ Reap[Sow[1, list], _, {#, Tr@#2} &], {x_, 4} :> x] when we need to select the elements repated greater than 4 times ? – developer2000 Jan 13 '14 at 7:50
• @developer2000 just change the 4 in {x_, 4} :> x, as you would with the Tally solution. – Mr.Wizard Jan 13 '14 at 7:52
• I think that you did not understand me. I would select the elements that repeated 4 times, 5 times, 6 times and so on (greater than 4). I think that I can use Table[Cases[stringTally @ list, {x_, i} :> x],{i,4,n}] but is there any other pretty solution? – developer2000 Jan 13 '14 at 9:02
• @developer2000 Oh, that was not clear. Do you mean that you wish to list the elements that appear four times separately from those that appear five times, etc., or list all elements that appear at least four times? – Mr.Wizard Jan 13 '14 at 9:10
• I want to list all elements that appear at least four times. sorry for the bed english. – developer2000 Jan 13 '14 at 11:37
DeleteDuplicates[Select[list, Count[list, #] == 4 &]]


Or be lazy and just run the set theory-inspired Union[] command over the result of your initial computation, provided that the initial one yields the results you listed -- it doesn't for me.

• sometimes being lazy is a good choice!! I know this solution! – developer2000 Jan 13 '14 at 18:20