# List all “duplicate” elements in Tally

Tally[list,test] can use a custom function test to judge if elements are equal. But the output will only give the first element in a group. Is there an option to give all the elements? Or how do I write a custom function to do this?

E.g. Given {{1,1},{1,2},{1,2,3},{2,3}}, a tally with test set to head equality would give {{{1,1},3},{{2,3},1}}, but I want something like {{3,{1,1},{1,2},{1,2,3}},{1,{2,3}}}.

• Possibly GatherBy is what you need but without more specifics I can't say for sure. – Andy Ross Jul 29 '15 at 4:04
• As Andy says, seems like a union against a Gather is what you're after, but you need to give a more useful description. – ciao Jul 29 '15 at 4:06
• See if Map[{#, Length@#} &, Union /@ Gather[#, <test>]] &@<object> is what you're after, with <test> being the equality test and <object> the target... – ciao Jul 29 '15 at 4:13
• @ciao Why Gather rather than GatherBy? – Mr.Wizard Jul 29 '15 at 4:21
• @ciao That's a worthy consideration, but I'll also mention that GatherBy is faster when applicable. – Mr.Wizard Jul 29 '15 at 4:26

As has been discussed in the comments you can also use GatherBy.

d = {{1, 1}, {1, 2}, {1, 2, 3}, {2, 3}};
{Length[#], Sequence @@ #} & /@ GatherBy[d, First]

(*{{3, {1, 1}, {1, 2}, {1, 2, 3}}, {1, {2, 3}}}*)

• can also be written {Length@{##}, ##} & @@@ GatherBy[d, First] for terse-freaks like me. :^) – Mr.Wizard Jul 29 '15 at 4:46
• @Mr.Wizard I'm one as well but clearly my kung fu is not as strong as yours :) – Andy Ross Jul 29 '15 at 4:51
• lol -- thanks, I think :-) ; since you go for this brand of weirdness: # ~Prepend~ Length@# & /@ d ~GatherBy~ First (or with {Length@#} ~Join~ # ...) – Mr.Wizard Jul 29 '15 at 4:51
• @Mr.Wizard infix is a lovely obfuscator. If only there were short aliases for built in symbols for the purpose of code golf. Accessed via On["Golf"]. Though <<Golf' is probably better. – Andy Ross Jul 29 '15 at 4:58
Map[{Length@#, #} &, Union /@ Gather[#, First[#1] === First[#2] &]] &@{{1, 1}, {1, 2}, {1, 2, 3}, {2, 3}}

(* {{3, {{1, 1}, {1, 2}, {1, 2, 3}}}, {1, {{2, 3}}}} *)


Do note, you've reversed the order of tally output in your example (which the above follows): tally puts element first, then count.

If you want all elements including duplications, remove the Union/@... replace the equality test with seasoning of your choice.

Just a Reap/Sow variant.

test = {{1, 1}, {1, 2}, {1, 2, 3}, {2, 3}};
Last@Reap[Sow[{##}, #] & @@@ test, _, {Length@#2, #2} &]