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}
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}
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]
]
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.5460.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 ?
– developer2000
Jan 13 '14 at 07:50
4 in {x_, 4} :> x, as you would with the Tally solution.
– Mr.Wizard
Jan 13 '14 at 07:52
Table[Cases[stringTally @ list, {x_, i} :> x],{i,4,n}] but is there any other pretty solution?
– developer2000
Jan 13 '14 at 09:02
Tr@ to sum a list of 1's wouldn't it be even faster to use Length@?
– george2079
Sep 30 '15 at 20:41
Tr is habit from totaling binary lists.
– Mr.Wizard
Oct 11 '15 at 08:24
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– Ajasja Jan 13 '14 at 07:08Cases[Tally[list], {i_, 4}:>i]– Rojo Jan 13 '14 at 07:09