# Sort nested list by a fixed order

I have a nested list like this one:

list={{{a,1},{b,3},{c,5}},{{b,1},{c,3},{a,5}},{{c,1},{b,3},{a,5}},{{a,1},{c,3},{b,5}}}

Now I need to sort the list such that the order within a row is always {{a,..},{b,..},{c,..}}. Put differently: the order of the first elements within the sublists should always be a, b and then c.

• SortBy[First] /@ list Nov 15, 2021 at 6:20

ClearAll[sortLike]
sortLike[refcolumn_, orderlike_] :=
Map[#[[Ordering[#[[All, refcolumn]]][[Ordering @ Ordering @ orderlike]]]] &]


Examples:

list = {{{a, 1}, {b, 3}, {c, 5}}, {{b, 1}, {c, 3}, {a, 5}},
{{c, 1}, {b, 3}, {a, 5}}, {{a, 1}, {c, 3}, {b, 5}}};

sortLike[1, {a, b, c}]@list // Column


sortLike[1, {b, a, c}]@list // Column


sortLike[2, {1, 2, 10}]@list // Column


sortLike[2, {5, 1, 3}]@list // Column


The argument orderlike can be given alternative ways to get the same result:

Multicolumn[Labeled[Column[sortLike[1, #]@list],
Row[{"orderlike: ", Style[#, ShowStringCharacters -> True]}], Top] & /@
{{c, a, b}, {"c", "a", "b"}, {"FOO", "BAR", "BUZZ"}, {3, 1, 2},
{100, 0, 25}, foo[10, 1, 9]}, 3,
Dividers -> All, Alignment -> Center]


• Nice answer! That way it is general. Nov 19, 2021 at 19:42

Something like the following:

Map[Sort[#] &, list]
(*{{{a, 1}, {b, 3}, {c, 5}}, {{a, 5}, {b, 1}, {c, 3}}, {{a, 5}, {b, 3}, {c, 1}}, {{a, 1}, {b, 5}, {c, 3}}}*)


A first approximation:

MyOrderList[list_List, order_?(Positive[#] && Element[#, Integers] &)] :=
Block[{slist, perm, mylist},
slist := Map[Sort, list];
perm = Mean[Map[Composition[Length, Permutations[#] &], slist]];
mylist :=
Table[Table[Extract[Select[Tuples[slist[[i]], Length[slist[[i]]]],
ContainsAll[#, slist[[i]]] &], j], {i, 1, Length[slist]}], {j, 1, perm}][[order]];
Return[If[order <= perm, mylist, HoldForm[MyOrderList]]];
];

Tests:

MyOrderList[list, 1]
(*{{{a, 1}, {b, 3}, {c, 5}}, {{a, 5}, {b, 1}, {c, 3}}, {{a, 5},
{b, 3}, {c, 1}}, {{a, 1}, {b, 5}, {c, 3}}}*)
MyOrderList[list, 2]
(*{{{a, 1}, {c, 5}, {b, 3}}, {{a, 5}, {c, 3}, {b, 1}}, {{a, 5},
{c, 1}, {b, 3}}, {{a, 1}, {c, 3}, {b, 5}}}*)
MyOrderList[list, 3]
(*{{{b, 3}, {a, 1}, {c, 5}}, {{b, 1}, {a, 5}, {c, 3}}, {{b, 3},
{a, 5}, {c, 1}}, {{b, 5}, {a, 1}, {c, 3}}}*)
MyOrderList[list,4]
(*{{{b, 3}, {c, 5}, {a, 1}}, {{b, 1}, {c, 3}, {a, 5}}, {{b, 3},
{c, 1}, {a, 5}}, {{b, 5}, {c, 3}, {a, 1}}}*)
MyOrderList[list,5]
(*{{{c, 5}, {a, 1}, {b, 3}}, {{c, 3}, {a, 5}, {b, 1}}, {{c, 1},
{a, 5}, {b, 3}}, {{c, 3}, {a, 1}, {b, 5}}}*)
MyOrderList[list,6]
(*{{{c, 5}, {b, 3}, {a, 1}}, {{c, 3}, {b, 1}, {a, 5}}, {{c, 1},
{b, 3}, {a, 5}}, {{c, 3}, {b, 5}, {a, 1}}}*)


Another approach using the idea of @cvgmt:

  MyOrderList[list_List, order_List] :=
Block[{slist, sorder, ordering, mylist},
slist := Map[Sort, list];
ordering :=
Extract[Permute[Ordering[Sort[order]], Ordering[#]] & /@
Permutations[order], {1}];(*@cvgmt*)
mylist := Table[slist[[i]][[ordering]], {i, 1, Length[slist]}];
Return[mylist];
];


Test:

MyOrderList[list, {b, c, a}]
(*{{{b, 3}, {c, 5}, {a, 1}}, {{b, 1}, {c, 3}, {a, 5}}, {{b, 3},
{c, 1}, {a, 5}}, {{b, 5}, {c, 3}, {a, 1}}}*)


Another approach using the idea of @kglr:

 MyOrderList[list_List, order_List] :=
Block[{slist, sorder, ordering, mylist},
slist := Map[Sort, list];
ordering :=
Extract[Map[Ordering@*Ordering, Permutations[order]], {1}];(*@kglr*)
mylist := Table[slist[[i]][[ordering]], {i, 1, Length[slist]}];
Return[mylist];
];


Test:

MyOrderList[list, {c, a, b}]
(*{{{c, 5}, {a, 1}, {b, 3}}, {{c, 3}, {a, 5}, {b, 1}}, {{c, 1},
{a, 5}, {b, 3}}, {{c, 3}, {a, 1}, {b, 5}}}*)

• This can be abbreviated by noting that Map[Sort[#] &, list] === Map[Sort, list] === Sort /@ list Nov 14, 2021 at 22:04
• This is all very nice but now lets assume I want the order to be {{b,..},{c,..},{a,..}}?? Is there a way to define a fixed predefined order? I'm sorry my question was not exact enough. I used a, b and c to keep it very simple.. e.g. the first elements could also be some text strings...
– M.A.
Nov 15, 2021 at 21:59
• @M.A. ReplaceAll[Thread[{a, b, c} -> {b, c, a}]][Map[Sort, list]] Nov 16, 2021 at 4:29
• @E.Chan-López This changes the structure of the list!! Besides this, your code does not work if you replace a, b,c with strings...
– M.A.
Nov 19, 2021 at 6:29