Herz im Kopf Optimismusbarometer   
Lesezeichen [ Info # QR-Code # Publikationen ]So 22 Okt 2017 22:41:57 # Grundlagen der Programmierung | Tcl Tutorial.


. More Array Commands - Iterating and use in procedures .

[ Previous | Index | Next ]

Often you will want to loop through the contents of an associative array - without having to specify the elements explicitly. For this the array names and array get commands are very useful. With both you can give a (glob-style) pattern to select what elements you need:

 foreach name [array names mydata] {
  puts "Data on \"$name\": $mydata($name)"

 # Get names and values directly

 foreach {name value} [array get mydata] {
  puts "Data on \"$name\": $value"

Note, however, that the elements will not be returned in any predictable order: this has to do with the underlying "hash table". If you want a particular ordering (alphabetical for instance), use code like:

 foreach name [lsort [array names mydata]] {
  puts "Data on \"$name\": $mydata($name)"

While arrays are great as a storage facility for some purposes, they are a bit tricky when you pass them to a procedure: they are actually collections of variables. This will not work:

 proc print12 {a} {
  puts "$a(1), $a(2)"

 set array(1) "A"
 set array(2) "B"

 print12 $array

The reason is very simple: an array does not have a value. Instead the above code should be:

 proc print12 {array} {
  upvar $array a
  puts "$a(1), $a(2)"

 set array(1) "A"
 set array(2) "B"

 print12 array

So, instead of passing a "value" for the array, you pass the name. This gets aliased (via the upvar command) to a local variable (that behaves the as original array). You can make changes to the original array in this way too.


. Example .

   # The example of the previous lesson revisited - to get a
   # more general "database".

   proc addname {db first last} {
    upvar $db name

    # Create a new ID (stored in the name array too for easy access).

    incr name(ID)
    set id $name(ID)

    set name($id,first) $first   ;# The index is simply a string!
    set name($id,last)  $last    ;# So we can use both fixed and
                                 ;# varying parts.

   proc report {db} {
    upvar $db name

    # Loop over the last names: make a map from last name to ID.

    foreach n [array names name "*,last"] {

     # Split the name to get the ID - the first part of the name!

     regexp {^[^,]+} $n id

     # Store in a temporary array:
     # an "inverse" map of last name to ID.

     set last       $name($n)
     set tmp($last) $id

    # Now we can easily print the names in the order we want!

    foreach last [lsort [array names tmp]] {
     set id $tmp($last)
     puts "$name($id,first) $name($id,last)"

   # Initialise the array and add a few names.

   set fictional_name(ID) 0
   set historical_name(ID) 0

   addname fictional_name Mary Poppins
   addname fictional_name Uriah Heep
   addname fictional_name Frodo Baggins

   addname historical_name Rene Descartes
   addname historical_name Richard Lionheart
   addname historical_name Leonardo "da Vinci"
   addname historical_name Charles Baudelaire
   addname historical_name Julius Caesar

   # Some simple reporting

   puts "Fictional characters:"
   report fictional_name
   puts "Historical characters:"
   report historical_name

[ Home | Top ]
[ . Previous | Index | Next . ]
Der Inhalt dieser Seite wurde am 24.05.2016 um 12.17 Uhr aktualisiert.
Navigation Seminare Magic Software Projekte Publikationen Kontakt Home
   huecker dot com * Germany
© 1999, 2017 Franz-Josef Hücker. All Rights Reserved.
Send Page Print Page LinkedIn follow me on twitter RSS Feeds & Podcasts