Tcl Tutorial Lesson 22

Difference between version 2 and 3 - Previous - Next

**Associative Arrays.**


!!!!!!
'''[Tcl Tutorial Lesson 21%|%Previous lesson%|%]''' | '''[Tcl Tutorial Index%|%Index%|%]''' | '''[Tcl Tutorial Lesson 23%|%Next lesson%|%]'''
!!!!!!



Languages like C, BASIC, Fortran and Java support arrays in which the index value is an integer.  Tcl, like most scripting languages (Perl, Python, PHP, etc...)  supports associative arrays (also known as "hash tables") in which the index value is a string.

The syntax for an associative array is to put the index within parentheses:
======
set name(first) "Mary"
set name(last)  "Poppins"

puts "Full name: $name(first) $name(last)"
======




There are several array commands aside from simply accessing and creating arrays which will be discussed in this and the next lesson.

   `array exists arrayName`:    Returns 1 if `arrayName` is an array variable.  Returns 0 if `arrayName` is a scalar variable, proc, or does not exist.

   `array names arrayName ?pattern`:    Returns a list of the indices for the associative array `arrayName`.  If `pattern` is supplied, only those indices that match `pattern` are returned.  The match is done using the globbing technique from `string match`.

   `array size arrayName`:    Returns the number of elements in array `arrayName`.

   `array get arrayName`:    Returns a list of element names and element values. First the element name, then its value.

   `array set arrayName dataList`:    Converts a list into an associative array.  `dataList` is a list in the format of that returned by `array get`, so the name of an array element, followed by its value.
   `array unset arrayName ?pattern?`:    Unsets all of the elements in the array. whose names match `pattern`. If `pattern` exists, only the elemenits thated, matche patterntire areray is unset.

When an associative array name is given as the argument to the `global` command, all the elements of the associative array become available to that proc.  For this reason, ''Brent Welch'' recommends (in his book ''Practical Programming in Tcl and Tk'') using an associative array for the state structure in a package.

This method makes it simpler to share data between many procs that are working together, and doesn't pollute the global namespace as badly as using separate globals for all shared data items. (See also [Tcl Tutorial Lesson 31%|%Building reusable libraries - packages and namespaces%|%], though).

Another common use for arrays is to store tables of data.  In the example below we use an array to store a simple database of names.
----

***Examples***

****Example 1****

======
proc addname {first last} {
    global 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
}

#
# Initialise the array and add a few names
#
global name
set name(ID) 0

addname Mary Poppins
addname Uriah Heep
addname Rene Descartes
addname Leonardo "da Vinci"

#
# Check the contents of our database
# The parray command is a quick way to
# print it
#
parray name
======

<<discussion>> Resulting output
======none
name(1,first) = Mary
name(1,last)  = Poppins
name(2,first) = Uriah
name(2,last)  = Heep
name(3,first) = Rene
name(3,last)  = Descartes
name(4,first) = Leonardo
name(4,last)  = da Vinci
name(ID)      = 4
======
<<enddiscussion>>

****Example 2****
======
#
# Some array commands
#
array set array1 [list {123} {Abigail Aardvark} \
                       {234} {Bob Baboon} \
                       {345} {Cathy Coyote} \
                       {456} {Daniel Dog} ]

puts "Array1 has [array size array1] entries\n"

puts "Array1 has the following entries:\n [array names array1]\n"

puts "ID Number 123 belongs to $array1(123)\n"

if {[array exist array1]} {
    puts "array1 is an array"
} else {
    puts "array1 is not an array"
}

if {[array exist array2]} {
    puts "array2 is an array"
} else {
    puts "array2 is not an array"
}

proc existence {variable} {
    upvar $variable testVar
    if { [info exists testVar] } {
        puts "$variable Exists"
    } else {
        puts "$variable Does Not Exist"
    }
}
======

<<discussion>> Resulting output
======none
Array1 has 4 entries

Array1 has the following entries:
 345 234 123 456

ID Number 123 belongs to Abigail Aardvark

array1 is an array
array2 is not an array
======
<<enddiscussion>>

****Example 3****
======
# Create an array
for {set i 0} {$i < 5} {incr i} { set a($i) test }

puts "\ntesting unsetting a member of an array"
existence a(0)
puts "a0 has been unset"
unset a(0)
existence a(0)

puts "\ntesting unsetting several members of an array, part 2"
existence a(3)
existence a(4)
catch {unset a(3) a(0) a(4)}
puts "\nAfter attempting to delete a(3), a(0) and a(4)"
existence a(3)
existence a(4)

puts "\nUnset all the array's elements"
existence a
array unset a *

puts "\ntesting unsetting an array"
existence a
puts "a has been unset"
unset a
existence a
======

<<discussion>> Resulting output
======none

testing unsetting a member of an array
a(0) Exists
a0 has been unset
a(0) Does Not Exist

testing unsetting several members of an array, part 2
a(3) Exists
a(4) Exists

After attempting to delete a(3), a(0) and a(4)
a(3) Does Not Exist
a(4) Exists

Unset all the array's elements
a Exists

testing unsetting an array
a Exists
a has been unset
a Does Not Exist
======
<<enddiscussion>>


!!!!!!
'''[Tcl Tutorial Lesson 21%|%Previous lesson%|%]''' | '''[Tcl Tutorial Index%|%Index%|%]''' | '''[Tcl Tutorial Lesson 23%|%Next lesson%|%]'''
!!!!!!