3
$\begingroup$

I have a list of rules such as

listofrules = {{1, 1, 2, 5, 14} -> 1, {1, 1, 2, 7, 12} -> 1, {137, 1, 2, 6, 16} -> 
      1, {137, 1, 2, 8, 13} -> 1, {273, 1, 2, 3, 5} -> 
      1, {273, 1, 2, 3, 7} -> 2, {273, 1, 2, 9, 12} -> 
      1, {273, 1, 2, 9, 14} -> -2, {409, 1, 2, 3, 6} -> 
      1, {409, 1, 2, 3, 8} -> 
      2, {409, 1, 2, 9, 13} -> -1, {409, 1, 2, 9, 16} -> 
      2, {545, 1, 2, 4, 5} -> 1, {577,1,1,1,1} -> -3 ...... , {9520, 16, 16, 13, 16} -> 2, {9520, 16, 16, 1, 1} -> 
      2, {9520, 16, 16, 2, 2} -> -2, {9520, 16, 16, 5, 5} -> -4, {9520, 
       16, 16, 6, 6} -> 
      3, {9520, 16, 16, 7, 7} -> -12, {9520, 16, 16, 8, 8} -> -1, {9520, 
       16, 16, 10, 10} -> -1, {9520, 16, 16, 12, 12} -> -4, {9520, 16, 16,
        13, 13} -> 
      3, {9520, 16, 16, 14, 14} -> -12, {9520, 16, 16, 15, 15} -> 
      4, {9520, 16, 16, 16, 16} -> -1}

I want to sort it, ordering the last four elements of the LHS in growing order, irrespective of the first element.

For example, I want all the rules {#,1,1,1,1} -> # first, then all the rules {#,1,1,1,2} -> # etc...

How can I do that in an efficient way?

$\endgroup$

3 Answers 3

4
$\begingroup$

Try

listofrules={
  {1,1,2,5,14}->1,{1,1,2,7,12}->1,{137,1,2,6,16}->1,{137,1,2,8,13}->1,
  {273,1,2,3,5}->1,{273,1,2,3,7}->2,{273,1,2,9,12}->1,{273,1,2,9,14}->-2,
  {409,1,2,3,6}->1,{409,1,2,3,8}->2,{409,1,2,9,13}->-1,{409,1,2,9,16}->2,
  {545,1,2,4,5}->1,{577,1,1,1,1}->-3,{9520,16,16,13,16}->2,{9520,16,16,1,1}->2,
  {9520,16,16,2,2}->-2,{9520,16,16,5,5}->-4,{9520,16,16,6,6}->3,
  {9520,16,16,7,7}->-12,{9520,16,16,8,8}->-1,{9520,16,16,10,10}->-1,
  {9520,16,16,12,12}->-4,{9520,16,16,13,13}->3,{9520,16,16,14,14}->-12,
  {9520,16,16,15,15}->4,{9520,16,16,16,16}->-1};
SortBy[listofrules,#[[1,{2,3,4,5}]]&]

which extracts the items that you want to sort by and thus returns

{{577, 1, 1, 1, 1} -> -3, {273, 1, 2, 3, 5} -> 1, {409, 1, 2, 3, 6} -> 1, 
 {273, 1, 2, 3, 7} -> 2, {409, 1, 2, 3, 8} -> 2, {545, 1, 2, 4, 5} -> 1, 
 {1, 1, 2, 5, 14} -> 1, {137, 1, 2, 6, 16} -> 1, {1, 1, 2, 7, 12} -> 1, 
 {137, 1, 2, 8, 13} -> 1, {273, 1, 2, 9, 12} -> 1, {409, 1, 2, 9, 13} -> -1, 
 {273, 1, 2, 9, 14} -> -2, {409, 1, 2, 9, 16} -> 2, {9520, 16, 16, 1, 1} -> 2, 
 {9520, 16, 16, 2, 2} -> -2, {9520, 16, 16, 5, 5} -> -4, {9520, 16, 16, 6, 6} -> 3, 
 {9520, 16, 16, 7, 7} -> -12, {9520, 16, 16, 8, 8} -> -1, 
 {9520, 16, 16, 10, 10} -> -1, {9520, 16, 16, 12, 12} -> -4, 
 {9520, 16, 16, 13, 13} -> 3, {9520, 16, 16, 13, 16} -> 2, 
 {9520, 16, 16, 14, 14} -> -12, {9520, 16, 16, 15, 15} -> 4, 
 {9520, 16, 16, 16, 16} -> -1}

For this particular choice of the items to sort by

SortBy[listofrules,Rest[#[[1]]]&]

will also work. And there are probably several other ways of selecting the desired four elements.

$\endgroup$
3
  • $\begingroup$ Thank you, it works! Can you explain me what #[[1,{2,3,4,5}]]&] does, please? $\endgroup$
    – Hegel19
    Commented Aug 4, 2020 at 8:39
  • 2
    $\begingroup$ Sure. Part of the culture of Mathematica is to turn lots of stuff into punctuation characters. Stuff followed by & is a function, but we just use it and don't give it any name, look at the documentation reference.wolfram.com/language/ref/Function.html This function is going to have a single argument and that is indicated by # which will be any one of the items in your list. Then #[[1]] will extract the first part of your rule. And #[[1,{2,3,4,5}]] is going to extract the 2nd through 5th items out of that first part. SortBy uses this to extract the items to sort by. Is that enough? $\endgroup$
    – Bill
    Commented Aug 4, 2020 at 8:53
  • $\begingroup$ Perhaps compare this f[r_]:=r[[1,{2,3,4,5}]]; SortBy[listofrules,f] to the #& version and see if that helps you a little. You can also search the help system for things like [[ and that will provide some explanation on how this is extracting the desired bits. $\endgroup$
    – Bill
    Commented Aug 4, 2020 at 17:08
4
$\begingroup$
#[[Ordering[#[[All, 1, 2 ;;]]]]] & @ listofrules 
{{577, 1, 1, 1, 1} -> -3, {273, 1, 2, 3, 5} -> 1, {409, 1, 2, 3, 6} -> 1, 
{273, 1, 2, 3, 7} ->  2, {409, 1, 2, 3, 8} -> 2, {545, 1, 2, 4, 5} -> 1, 
{1, 1, 2, 5, 14} -> 1, {137, 1, 2, 6, 16} -> 1, {1, 1, 2, 7, 12} -> 1, 
{137, 1, 2, 8, 13} -> 1, {273, 1, 2, 9, 12} -> 1, {409, 1, 2, 9, 13} -> -1,
{273, 1, 2, 9, 14} -> -2, {409, 1, 2, 9, 16} -> 2, {9520, 16, 16, 1, 1} -> 2, 
{9520, 16, 16, 2, 2} -> -2, {9520, 16, 16, 5, 5} -> -4, 
{9520, 16, 16, 6, 6} -> 3, {9520, 16, 16, 7, 7} -> -12, {9520, 16, 16, 8, 8} -> -1, 
{9520, 16, 16, 10, 10} -> -1, {9520, 16, 16, 12, 12} -> -4, 
{9520, 16, 16, 13, 13} -> 3, {9520, 16, 16, 13, 16} -> 2, 
{9520, 16, 16, 14, 14} -> -12, {9520, 16, 16, 15, 15} -> 4, 
{9520, 16, 16, 16, 16} -> -1}

This should be faster than SortBy for long lists.

$\endgroup$
2
  • $\begingroup$ How come two # and one &? How should I think about that? $\endgroup$ Commented Aug 4, 2020 at 15:33
  • 1
    $\begingroup$ @PaulCommentary, alternatively, we can define the function #[[Ordering[#[[All, 1, 2 ;;]]]]] & as foo[x_] := x[[Ordering[x[[All, 1, 2 ;;]]]]] and use it as foo[listofrules]. $\endgroup$
    – kglr
    Commented Aug 4, 2020 at 15:42
2
$\begingroup$

Another possibility using operator forms (and avoiding pure functions) is:

SortBy[listofrules, Rest @* First]

{{577, 1, 1, 1, 1} -> -3, {273, 1, 2, 3, 5} -> 1, {409, 1, 2, 3, 6} -> 1, {273, 1, 2, 3, 7} -> 2, {409, 1, 2, 3, 8} -> 2, {545, 1, 2, 4, 5} -> 1, {1, 1, 2, 5, 14} -> 1, {137, 1, 2, 6, 16} -> 1, {1, 1, 2, 7, 12} -> 1, {137, 1, 2, 8, 13} -> 1, {273, 1, 2, 9, 12} -> 1, {409, 1, 2, 9, 13} -> -1, {273, 1, 2, 9, 14} -> -2, {409, 1, 2, 9, 16} -> 2, {9520, 16, 16, 1, 1} -> 2, {9520, 16, 16, 2, 2} -> -2, {9520, 16, 16, 5, 5} -> -4, {9520, 16, 16, 6, 6} -> 3, {9520, 16, 16, 7, 7} -> -12, {9520, 16, 16, 8, 8} -> -1, {9520, 16, 16, 10, 10} -> -1, {9520, 16, 16, 12, 12} -> -4, {9520, 16, 16, 13, 13} -> 3, {9520, 16, 16, 13, 16} -> 2, {9520, 16, 16, 14, 14} -> -12, {9520, 16, 16, 15, 15} -> 4, {9520, 16, 16, 16, 16} -> -1}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.