# 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 Commented Jan 13, 2014 at 7:08
• Cases[Tally[list], {i_, 4}:>i]
– Rojo
Commented Jan 13, 2014 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 Commented Jan 13, 2014 at 7:18
• Cases[Tally[list], {x_, 4} -> x] seems to work too. Commented Jan 28, 2014 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 ? Commented Jan 13, 2014 at 7:50
• @developer2000 just change the 4 in {x_, 4} :> x, as you would with the Tally solution. Commented Jan 13, 2014 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? Commented Jan 13, 2014 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? Commented Jan 13, 2014 at 9:10
• I want to list all elements that appear at least four times. sorry for the bed english. Commented Jan 13, 2014 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! Commented Jan 13, 2014 at 18:20