Wednesday 8 May 2013

Sort

Sort is a very useful and dangerous function at the same time, let's analyze it.
First of all, it changes the series:

>> a: [ 5 8 7 9 2 3 1 4]
>> sort a
>> a
== [1 2 3 4 5 7 8 9]


when you experiment your code with sort, I suggest you to create a backup of the original series.

Sort is handy also with very complex bocks, you can specify the length of every row:

>> a: [
"Max" $45 5-5-2005
"Carl" $550 21-3-2000
"Mario" $1000 3-3-1999
]
>> sort/skip a 3
== [
"Carl" $550.00 21-Mar-2000
"Mario" $1000.00 3-Mar-1999
"Max" $45.00 5-May-2005
]


Moreover, you can specify what row to use for sorting. For example let's sort by 3rd and then by 2nd column:


>> a: [
"Max" $45 5-5-2005
"Carl" $550 21-3-2000
"Mario" $1000 3-3-1999
]
>> sort/skip/compare a 3 [3 2 ]
== [
"Mario" $1000.00 3-Mar-1999
"Carl" $550.00 21-Mar-2000
"Max" $45.00 5-May-2005
]


Sort always sort in ascending way (from lower to higher). If you want a more complex sorting, some ascending and some descending), you need mks. MKS is a sort helping function, it works that way:
  • remember to add /all refinement
  • if you indicate a column with a positive number, sorting with that column will be in ascending order
  • if you indicate a column with a negative number, sorting with that column will be in descending order
Example:

>> sort/skip/compare/all a 3 mks [-3 2 ]


Here is the mks source code:
REBOL [
    Title: "Sort by multiple keys"
    Date: 17-Apr-2006
    File: %multiple-key-sort.r
    Author: "Cesar Chavez"
    Purpose: {Function to sort series with more than one field per record, by multiple keys, in any position and in ascending or descending order each one of them.}
    Version: 1.1.1 ; majorv.minorv.status   ; status: 0: unfinished; 1: testing; 2: stable    
    ]
mks: func [keys [block!]/local keyr f1 f2 i j x y o][
    o: copy "> <"
    keyr: reverse copy keys
    x: copy ""
    y: copy ""
    f2: copy []
    foreach e keyr [
        if error? try [i: abs e][return [0]]
        if error? try [j: (e / i) + 2][return [0]]
        append f2 rejoin [x "a/" i " " o/:j " b/" i y]
        x: "]["
        y: "]"
    ]
    f1: copy []
    repeat k (length? keys) - 1 [
        i: abs keys/:k
        append f1 rejoin ["either = a/" i " b/" i " ["]
    ]
    first reduce load rejoin ["func [a b] [" f1 f2 "]"]
]

No comments:

Post a Comment