Numbered arrays

Richard Suchenwirth 1999-11-15 -- Tcl arrays do not preserve the order in which elements are added. You can have this behavior by assigning sortable keys that reflect the order of adding elements: Here's a quick working sketch (will lose order with the millionth element) which builds array keys of both a running ID number and an input key :

 proc array:addn {_a key value} {
   upvar $_a a
   set last [lindex [lsort [array names a]] end]
   set no [lindex [split $last ,] 0]
   if {![string length $no]} {set no 0}
   incr no
   set a([format %06.6d $no],$key) $value
 }

 array:addn foo bar testing
 testing
 array:addn foo baz testing2
 testing2
 foreach i [lsort [array names foo]] {puts $i:$foo($i)}
 000001,bar:testing                                           ~
 000002,baz:testing2
#... and here's a quick-and dirty retriever for a keyed element:
 proc array:getn {_a key} {
   upvar $_a a
   set a([array names a *,$key])
 }
 array:getn foo bar
 testing
 array:getn foo barry
 can't read "a()": no such element in array

Stephen Trier - The wonderful -dictionary option to lsort solves the millionth-element problem:

 proc array:addn {_a key value} {
   upvar $_a a
   set last [lindex [lsort -dictionary [array names a]] end]
   set no [lindex [split $last ,] 0]
   if {![string length $no]} {set no 0}
   incr no
   set a($no,$key) $value
 }

 foreach x {foo bar a b c d e f g h i j k l} {
     array:addn foo $x "testing $x"
 }
 foreach i [lsort -dictionary [array names foo]] {puts $i:$foo($i)}
 1,foo:testing foo
 2,bar:testing bar
 3,a:testing a
 4,b:testing b
 5,c:testing c
 6,d:testing d
 7,e:testing e
 8,f:testing f
 9,g:testing g
 10,h:testing h
 11,i:testing i
 12,j:testing j
 13,k:testing k
 14,l:testing l

Now we're good for a couple billion elements.