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}
Mathematica Stack Exchange is a question and answer site for users of Wolfram Mathematica. It only takes a minute to sign up.
Sign up to join this communityYou 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]
]
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]
]
Cases[Last @ Reap[Sow[1, list], _, {#, Tr@#2} &], {x_, 4} :> x]
when we need to select the elements repated greater than 4 times ?
$\endgroup$
Jan 13, 2014 at 7:50
4
in {x_, 4} :> x
, as you would with the Tally
solution.
$\endgroup$
Jan 13, 2014 at 7:52
Table[Cases[stringTally @ list, {x_, i} :> x],{i,4,n}]
but is there any other pretty solution?
$\endgroup$
Jan 13, 2014 at 9:02
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.
DeleteDuplicates
$\endgroup$Cases[Tally[list], {i_, 4}:>i]
$\endgroup$