Main Content

Sorting in Tcl - lists and arrays

Archive - Originally posted on "The Horse's Mouth" - 2007-10-24 20:05:46 - Graham Ellis

Tcl's lsort command lets you sort a list - and that can be a list of the keys of an array. You can't sort the array, but once you have the list of keys you can sort that and use it to iterate through the array in any order that you like.

As everything (except an array) is a string in Tcl, when you sort a list the language defaults to an asciibetic sort - which you can vary with the -integer or -real options to lsort. And if you want to specify another criterion, you can do that too, using the -command option to specify the name of a proc that returns -1, 0 or +1 to indicate the ordering of two input records.

There's examples of all three following - I'm sorting a list of keys from an array asciibetically, numerically, and by the value that the key points to:

proc report {order say} {
  puts $say
  global stop
  foreach pl $order {
    puts "$pl: $stop($pl)"
  }
}
#
proc byp {a b} {
  global stop
  return [string compare $stop($a) $stop($b)]
}
#
set stop(1) Bath
set stop(2) Bristol
set stop(6) Keynsham
set stop(3) Easterton
set stop(4) unused
set stop(5) unused
set stop(10) London
set stop(11) "The West"
#
set bystop [lsort [array names stop]]
set properbystop [lsort -integer [array names stop]]
set byplace [lsort -command byp [array names stop]]
#
report $bystop "By Ascii stop"
report $properbystop "By numeric stop"
report $byplace "By place name"


Here are the results:

earth-wind-and-fire:~/oct07/camb grahamellis$ tclsh allsorts
By Ascii stop
1: Bath
10: London
11: The West
2: Bristol
3: Easterton
4: unused
5: unused
6: Keynsham
By numeric stop
1: Bath
2: Bristol
3: Easterton
4: unused
5: unused
6: Keynsham
10: London
11: The West
By place name
1: Bath
2: Bristol
3: Easterton
6: Keynsham
10: London
11: The West
4: unused
5: unused
earth-wind-and-fire:~/oct07/camb grahamellis$