Select a repeated element in a list
You may use Tally to finish the task as follows:
Cases[Tally[list], {x_, 4} :> x]
the result will be {a,b}.
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
Addendum
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]
]
DeleteDuplicates[Select[list, Count[list, #] == 4 &]]