REBOL 3 Docs Guide Concepts Functions Datatypes Errors
  TOC < Back Next >   Updated: 6-Feb-2009 Edit History  

REBOL 3 Concepts: Series: Sorting Series

Pending Revision

This document was written for R2 and has yet to be revised for R3.

The sort function offers a simple, quick method of sorting series. It is most useful for blocks of data, but can also be used on strings of characters.


Simple Sorting

The simplest examples of sort are:

names: [Eve Luke Zaphod Adam Matt Betty]
probe sort names
[Adam Betty Eve Luke Matt Zaphod]
print sort [321.3 78 321 42 321.8 12 98]
12 42 78 98 321 321.3 321.8
print sort "plosabelm"

Notice that sort is destructive to its argument series. It reorders the original data. To prevent this, use copy, as in the following example:

probe sort copy names

By default, sorting is case insensitive:

print sort ["Fred" "fred" "FRED"]
Fred fred FRED
print sort "G4C28f9I15Ed3bA076h"

Providing the /case refinement makes sorting case sensitive:

print sort/case "gCcAHfiEGeBIdbFaDh"
print sort/case ["Fred" "fred" "FRED"]
FRED Fred fred
print sort/case "g4Dc2BI8fCF9i15eAd3bGaE07H6h"

Many other datatypes can be sorted:

print sort []
print sort [$4.23 $23.45 $62.03 $23.23 $4.22]
$4.22 $4.23 $23.23 $23.45 $62.03
print sort [11:11:43 4:12:53 4:14:53 11:11:42]
4:12:53 4:14:53 11:11:42 11:11:43
print sort [11-11-1999 10-11-9999 11-4-1999 11-11-1998]
11-Nov-1998 11-Apr-1999 11-Nov-1999 10-Nov-9999
print sort [john@doe.dom jane@doe.dom jack@jill.dom]
jack@jill.dom jane@doe.dom john@doe.dom
print sort [%user.r %rebol.r %history.r %notes.html]
history.r notes.html rebol.r user.r

Group Sorting

Often it is necessary to sort a data set that has more than one value per record. The /skip refinement supports this for sorting records that have a fixed length. The refinement takes one additional argument: an integer specifying length of each record.

Here is an example that sorts a block that contains first name, last name, ages, and emails. The block is sorted by its first column, first-name.

names: [
    "Evie" "Jordan" 43 eve@jordan.dom
    "Matt" "Harrison" 87 matt@harrison.dom
    "Luke" "Skywader" 32 luke@skywader.dom
    "Beth" "Landwalker" 104 beth@landwalker.dom
    "Adam" "Beachcomber" 29 adam@bc.dom
sort/skip names 4
foreach [first-name last-name age email] names [
    print [first-name last-name age email]
Adam Beachcomber 29 adam@bc.dom
Beth Landwalker 104 beth@landwalker.dom
Evie Jordan 43 eve@jordan.dom
Luke Skywader 32 luke@skywader.dom
Matt Harrison 87 matt@harrison.dom

Comparison Functions

The /compare refinement allows you to perform custom comparisons on the data being sorted. This refinement takes an additional argument, which is the comparison function to use for ordering the data.

A comparison function is written as a regular function that takes two arguments. These arguments are the values to be compared. A comparison function returns true if the first value should be placed before the second value and false if the first value should be placed after the second value.

A normal comparison places data in ascending order:

ascend: func [a b] [a < b]

If the first value is less than the second, then true is returned from the function and the first value is placed before the second value.

data: [100 101 -20 37 42 -4]
probe sort/compare data :ascend
[-20 -4 37 42 100 101]


descend: func [a b] [a > b]

If the first value is greater than the second value, then true is returned and the data is sorted with greater values first. The sort will descend from greater values.

probe sort/compare data :descend
[101 100 42 37 -4 -20]

Notice that in both cases the comparison function is passed by providing its name preceded with a colon. The name preceded with a colon causes the function to be passed to sort without first being evaluated. The comparison function could also be provided directly with:

probe sort/compare data func [a b] [a > b]
[101 100 42 37 -4 -20]

  TOC < Back Next > - WIP Wiki Feedback Admin