# Group list of lists by Total

I have some list which looks like

{{0,1},{4},{0,0,1},{2,0,1},{3,0,0},{3,1},{0,0,0,4}}


and I need to group lists with equal sum of elements in ascending order like

{{{0,1},{0,0,1}},{{2,0,1},{3,0,0}},{{4},{3,1},{0,0,0,4}}}


and for

{{0, 0, 0, 0, 0}, {1, 1, 0, 0, 0}, {1, 1, 1, 1, 0}, {1, 1, 0, 1, 1}, {0, 1, 1, 0, 0}, {0, 1, 1, 1, 1}, {0, 0, 1, 1, 0}, {0, 0, 0, 1, 1}}


I expected to see

{{{0, 0, 0, 0, 0}}, {{1, 1, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 1, 1}}, {{1, 1, 1, 1, 0}, {1, 1, 0, 1, 1}, {0, 1, 1, 1, 1}}}

-
BTW, I've noticed something disconcerting about you posting history; you've gotten great answers on many questions, but have accepted none. You should go through you questions and accept the best adequate answer for each one (it is ok to wait a day or so to see if you get any better, but be certain not to forget or people will get frustrated with you after a while.) – C. E. Oct 16 '13 at 15:48
Oh, sorry I didn't know. I'll do it tomorrow! – Филипп Цветков Oct 16 '13 at 16:35

Sort@GatherBy[{{0, 1}, {4}, {0, 0, 1}, {2, 0, 1}, {3, 0, 0}, {3, 1}, {0, 0, 0, 4}}, Total]


To make sure Sort always gets it right:

Sort[GatherBy[n, Total], Less[Total@First[#], Total@First[#2]] &]

-
n = {{0, 0, 0, 0, 0}, {1, 1, 0, 0, 0}, {1, 1, 1, 1, 0}, {1, 1, 0, 1, 1}, {0, 1, 1, 0, 0}, {0, 1, 1, 1, 1}, {0, 0, 1, 1, 0}, {0, 0, 0, 1, 1}}; Sort@GatherBy[n, Total]; gives {{{0, 0, 0, 0, 0}}, {{1, 1, 1, 1, 0}, {1, 1, 0, 1, 1}, {0, 1, 1, 1, 1}}, {{1, 1, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 1, 1}}} but I would like to get {{{0, 0, 0, 0, 0}}, {{1, 1, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 1, 1}}, {{1, 1, 1, 1, 0}, {1, 1, 0, 1, 1}, {0, 1, 1, 1, 1}}} – Филипп Цветков Oct 16 '13 at 13:53
Yes, it was only plain luck that the first version worked without having to use SortBy. But that's exactly why I added another version which, as I said, "always gets it right." (In the first version it works because the first number in each sublist is ascending in the way you would like to have it sorted. – C. E. Oct 16 '13 at 15:10
So just to be clear, the topmost solution is only valid for the first example you provided. Not for subsequent examples. But I foresaw this, and provided the first version only as a curiosity to show that in this particular case it's this simple. – C. E. Oct 16 '13 at 15:12
Your second line appears to be a SortBy[...,True]. This just defaults down to Sort again and makes it equal to your first solution. – jVincent Oct 16 '13 at 15:43
@jVincent Yeah, silly me. I corrected it. I sure would have appreciated some downvotes/comments to alert me! With seven upvotes you tend to think you have it right! Ty! (+1 for yours, I like it better. It should get at least 14 upvotes.) – C. E. Oct 16 '13 at 15:48

A simple approach is to just use:

GatherBy[SortBy[list,Total],Total]


This ensures that they appear in the correct order since they are gathered based on the appearance of the first element. In each sublist with the same total, they will be ordered based on OrderedQ, which puts them in order of number of elements afaik.

To verify that it works out:

 listA={{0,1},{4},{0,0,1},{2,0,1},{3,0,0},{3,1},{0,0,0,4}};
listB={{0, 0, 0, 0, 0, 1}, {4}, {0, 0, 0, 0, 1}, {2, 0, 1}, {3, 0, 0}, {3, 1}, {0, 0, 0, 4}};

verify[v_] := Total[First[#]] & /@ v
verify@GatherBy[SortBy[listA, Total], Total]
verify@GatherBy[SortBy[listB, Total], Total]
(* {1,3,4} *)
(* {1,3,4} *)

-

I would write it like this:

list ~SortBy~ {Total} ~SplitBy~ Total


Note that putting the SortBy function inside a list (i.e. {Total} instead of just Total) means that SortBy will give a stable sort, so elements with the same total will stay in the order they were in the original list.

-
neat idea! Thanks for sharing/explaining – Pinguin Dirk Oct 16 '13 at 16:33

Just for fun:

Pick[list, Total /@ list, #] & /@ Union[Total /@ list]


=> {{{0, 1}, {0, 0, 1}}, {{2, 0, 1}, {3, 0, 0}}, {{4}, {3, 1}, {0, 0, 0, 4}}}

where

list = {{0, 1}, {4}, {0, 0, 1}, {2, 0, 1}, {3, 0, 0}, {3, 1}, {0, 0,
0, 4}}


And

Pick[n, Total /@ n, #] & /@
Union[Total /@ n] == {{{0, 0, 0, 0, 0}}, {{1, 1, 0, 0, 0}, {0, 1, 1,
0, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 1, 1}}, {{1, 1, 1, 1, 0}, {1,
1, 0, 1, 1}, {0, 1, 1, 1, 1}}}


=> True

-