# How to tally a list of lists only by considering the first element of the sub list

We need to Tally a list of lists only by considering the first element of the sub lists and then sort the resulting list.

As a simple example consider

list={{1, a}, {2, b}, {3, c}, {1, d}, {1, b}, {3, g}, {4, a}, {3, f}, {3, c}}


We need the output as follows:

(* {{4, {{3, c}, {3, g}, {3, f}, {3, c}}},
{3, {{1, a}, {1, d},{1,b}}},
{1, {{2, b}}},
{1, {{4, a}}}} *)


Here the first element in the output {4, {{3, c}, {3, g}, {3, f}, {3, c}}} shows that 4 sub lists contains 3 as first element and so on.

Kindly help us in solving this problem.

Use GroupBy:

Values@GroupBy[list,#[[1]]&,{Length@#,#}&]


• It works, but we need to sort the result obtained to get the desired result
– SPJ
Commented Apr 25 at 14:46
• @SPJ Reverse@Sort@Values@GroupBy[list, First, {Length@#, #} &] Commented Apr 25 at 15:44
• @SPJ or SortBy[Values@GroupBy[list,#[[1]]&,{Length@#,#}&],-#[[1]]&] Commented Apr 25 at 19:31
Clear["Global*"];
list = {{1, a}, {2, b}, {3, c}, {1, d}, {1, b}, {3, g}, {4, a}, {3,
f}, {3, c}};
ord = SortBy[list, First] // GroupBy[#, First, Length] & //
ReverseSortBy[#, {Values}] & // Keys;
GatherBy[list, First] //
Replace[#, k_List :> {Length@k, k}, 1] & // #[[ord]] &


{{4, {{3, c}, {3, g}, {3, f}, {3, c}}}, {3, {{1, a}, {1, d}, {1, b}}}, {1, {{2, b}}}, {1, {{4, a}}}}

list =
{{1, a}, {2, b}, {3, c}, {1, d}, {1, b}, {3, g}, {4, a}, {3, f}, {3, c}}

la = Transpose[{Length /@ #, #}] & @ GatherBy[list, First]


{{3, {{1, a}, {1, d}, {1, b}}},
{1, {{2, b}}},
{4, {{3, c}, {3, g}, {3, f}, {3, c}}},
{1, {{4, a}}}}

lb = ReverseSortBy[First] @ la


{{4, {{3, c}, {3, g}, {3, f}, {3, c}}},
{3, {{1, a}, {1, d}, {1, b}}},
{1, {{4, a}}},
{1, {{2, b}}}}

To get the wanted result we swap the last two lists

SubsetMap[Reverse, lb, {-2, -1}]


{{4, {{3, c}, {3, g}, {3, f}, {3, c}}},
{3, {{1, a}, {1, d}, {1, b}}},
{1, {{2, b}}},
{1, {{4, a}}}}

There's a slight bit of ambiguity in your sorting. Here are a few ways...

ReverseSortBy[GroupBy[list, First, {Length@#, #} &], First] // Values


and...

ReverseSortBy[GroupBy[list, First, Comap[{Length, Identity}]], First] // Values


both give

{{4, {{3, c}, {3, g}, {3, f}, {3, c}}},
{3, {{1, a}, {1, d}, {1, b}}},
{1, {{4, a}}},
{1, {{2, b}}}}


In your expected output, however, the last two were switched. So maybe you want an additional layer of sorting based on the first element of the sublists, which could look like...

Sort[
GroupBy[list, First, Comap[{Length, Identity}]],
#1[[1]] >= #2[[1]] && #1[[2, 1, 1]] <= #2[[2, 1, 1]] &] // Values
`