George Peter Staplin Nov 28, 2008 - Hash tables are generally used to associate strings or values with other values. This is a simple implementation of such a thing in Tcl. Tcl's array and dict are similar, though implemented in C.
#By George Peter Staplin # #This is a simple demonstration of a hash table for Tcl implemented in Tcl. #We use a linear list of sublists. # #In Tcl lists are like C arrays, so this is quite efficient. # #You can store a hash table in a hash table, so it's less restricted than [array]. #This might be beneficial to those that aren't using [dict] or [objstructure]. proc hash-create {} { set numbuckets 500 return [lrepeat $numbuckets [list]] } proc hash str { set n 0 foreach c [split $str ""] { #This hash algorithm is like Tcl's core hash. set n [expr {$n + ($n << 3) + [scan $c %c]}] } return $n } proc hash-set {bucketsvar key value} { upvar 1 $bucketsvar buckets set numbuckets [llength $buckets] set hash [hash $key] set offset [expr {$hash % $numbuckets}] set sublist [lindex $buckets $offset] set existing [lsearch -exact -index 0 $sublist $key] if {$existing < 0} { #This is a new key that hashed to this bucket. lappend sublist [list $key $value] } else { #This is a key that is the same as a previous key. #Replace the bucket's sublist item. set sublist [lreplace $sublist $existing $existing [list $key $value]] } lset buckets $offset $sublist } proc hash-get {buckets key valuevar} { upvar 1 $valuevar value set numbuckets [llength $buckets] set hash [hash $key] set offset [expr {$hash % $numbuckets}] set sublist [lindex $buckets $offset] set existing [lsearch -exact -index 0 $sublist $key] if {$existing < 0} { #not found return 0 } set value [lindex $sublist $existing 1] #found return 1 } proc main {} { set h [hash-create] set key1 "Hello World!" set key2 "Goodbye World!" puts keyset1:[time { hash-set h $key1 123 }] puts keyset2:[time { hash-set h $key2 456 }] if {[hash-get $h $key1 value]} { puts "Found $value associated with: $key1" } if {[hash-get $h $key2 value]} { puts "Found $value associated with $key2" } if {[hash-get $h "invalid key" value]} { puts "Invalid key returned a value?" } hash-set h $key1 789 if {[hash-get $h $key1 value]} { puts "updated $key1 value is: $value" } } main