:TITLE: Introduction to dict: Nested Data and Looping
;#
;# RCSID: $Header: /home/cvs/TclTutor3/lesson/Tcl_English/Tcl_English45.lsn,v 1.2 2010/12/22 15:53:19 clif Exp $
;# Copyright (c) 1995 Clif Flynt
;# 9300 Fleming Rd.
;# Dexter, MI  48130
;# clif@cflynt.com
;# See file "NOTICE" for licensing terms.
;#
:LESSON_TEXT_START_LEVEL 0:
Dictionary data can be nested to implement a data structures similar
to a C array of structures, or a database of rows and columns.  Like
a database, each set of nested data must have a unique identifier for
the key.  A Dictionary can not include a duplicated key.

<P>

Consider a dataset like this:
<PRE><CODE>
KEY    FIRST    LAST      TITLE
1      Clif     Flynt     Tcl/Tk For Real Programmers
2      Clif     Flynt     Tcl/Tk: A Developer's Guide 2'nd edition
3      Brent    Welch     Practical Programming in Tcl/Tk
4      Michael  McClennan Effective Tcl/Tk Programming
5      Don      Libes     Exploring Expect
</CODE></PRE>
In a dict it would look like this:
<PRE><CODE>
1 {FIRST Clif LAST Flynt TITLE {Tcl/Tk For Real Programmers}}
2 {FIRST Clif LAST Flynt TITLE {Tcl/Tk: A Developer's Guide}}
...
</CODE></PRE>

The <CODE>dict set</CODE> command can be used to assign nested values.
<P>

When <CODE>dict set</CODE> is evaluated with multiple values they
represent successively nested key/key/.../value pairs.

<PRE><CODE>
#>  dict set test a 1 b 2 c 3
<B>a {1 {b {2 {c 3}}}}</B>
</CODE></PRE>

<P>
You can create the book data either:
<UL>
  <LI> Successive set commands to add data:
  <PRE><CODE>
    dict set books 1 FIRST Clif
    dict set books 1 LAST  Flynt
    ...
  </CODE></PRE>
  <LI> append data as a list:
  <PRE><CODE>
     dict set books 2 {FIRST Clif LAST Flynt TITLE "Tcl/Tk: A Developers Guide"}
     ...
  </CODE></PRE>
  <LI> append data as a dict:
  <PRE><CODE>
     dict set books 2 \
         [dict create FIRST Clif LAST Flynt TITLE "Tcl/Tk: A Developers Guide"]
     ...
  </CODE></PRE>
</UL>
<P>
  You can iterate through a list with the <CODE>dict for</CODE> and
code <CODE>dict with</CODE>
<P>
  <DL>
    <BR><DT><CODE>dict for <I>{keyVar valVar} $dictData {script} </I></CODE>
    <DD>Iterate through the list assigning keys to the <CODE>keyVar</CODE> and
    the associated values  to the <CODE>valVar</CODE>.  The contents of the
    <CODE>keyVar</CODE> and <CODE>valVar</CODE> are available to the script.

    <BR><DT><CODE>dict with<I> varName {script}</I></CODE>
    <DD>Assign values to variables named for the keys in the variable
    <CODE>varName</CODE> and evaluate <CODE>script</CODE>.  This may create
    or modify local variables.  The variables named for the keys will
    have the final value after evaluating the <CODE>script</CODE>
  </DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 1:

Dictionary data can be nested to implement a data structures similar
to a C array of structures, or a database of rows and columns.  Like
a database, each set of nested data must have a unique identifier for
the key.  A Dictionary can not include a duplicated key.

<P>

Consider a dataset like this:
<PRE><CODE>
KEY    FIRST    LAST      TITLE
1      Clif     Flynt     Tcl/Tk For Real Programmers
2      Clif     Flynt     Tcl/Tk: A Developer's Guide 2'nd edition
3      Brent    Welch     Practical Programming in Tcl/Tk
4      Michael  McClennan Effective Tcl/Tk Programming
5      Don      Libes     Exploring Expect
</CODE></PRE>

<P>

The dict would look like this:
<PRE><CODE>
1 {first clif last flynt title {Tcl/Tk For Real Programmers}}
2 {first clif last flynt title {Tcl/Tk: A Developer's Guide}}
...
</CODE></PRE>

The keys are <CODE>1,2,3,4,</CODE>and </CODE>5</CODE>, and the
value is another dict.  Each set of values is 
is a dict in which the keys are <CODE>first, last,</CODE> and
<CODE>title</CODE>.

<P>
The <CODE>dict set</CODE> command can be used to assign nested values.
<P>

When <CODE>dict set</CODE> is evaluated with multiple values they
represent successively nested key/key/.../value pairs.

<PRE><CODE>
#>  dict set test a 1 b 2 c 3
<B>a {1 {b {2 {c 3}}}}</B>
</CODE></PRE>

<P>
You can create the book data either:
<UL>
  <LI> Successive set commands to add data:
  <PRE><CODE>
    dict set books 1 first Clif
    dict set books 1 last  Flynt
    ...
  </CODE></PRE>
  <LI> append data as a list:
  <PRE><CODE>
     dict set books 2 {first clif last flynt title "Tcl/Tk: A Developers Guide"}
     ...
  </CODE></PRE>
</UL>
<P>
  You can iterate through a list with the <CODE>dict for</CODE> and
code <CODE>dict with</CODE>
<P>
  <DL>
    <BR><DT><CODE>dict for <I>{keyVar valVar} $dictData {script} </I></CODE>
    <DD>Iterate through the list assigning keys to the <CODE>keyVar</CODE> and
    the associated values  to the <CODE>valVar</CODE>.  The contents of the
    <CODE>keyVar</CODE> and <CODE>valVar</CODE> are available to the script.

    <BR><DT><CODE>dict with<I> varName {script}</I></CODE>
    <DD>Assign values to variables named for the keys in the variable
    <CODE>varName</CODE> and evaluate <CODE>script</CODE>.  This may create
    or modify local variables.  The variables named for the keys will
    have the final value after evaluating the <CODE>script</CODE>
  </DL>

The <CODE>dict for</CODE> and <CODE>dict with</CODE> commands are 
commonly used together, as shown in the examples.

:TEXT_END:

:LESSON_TEXT_START_LEVEL 2:
Each key in a dictionary can only have a single value.  You can't
use the same key with two different values.  If you assign a new
value to a given key, it changes the value associated with that key.

<P>
However, some programs need sets of data with the same keys - for
instance a set of books will have a key named "title" for each book.

<P>
This is implemented using a nested dictionaries.  The top level
keys can be unique and the value associated with that key
is a new dict each of which has it's own set of key/value pairs.

<P>
Dictionary data can be nested to implement a data structures similar
to a C array of structures, or a database of rows and columns.  Like
a database, each set of nested data must have a unique identifier for
the key.  A Dictionary can not include a duplicated key.

<P>

Consider a dataset like this:
<PRE><CODE>
KEY    FIRST    LAST      TITLE
1      Clif     Flynt     Tcl/Tk For Real Programmers
2      Clif     Flynt     Tcl/Tk: A Developer's Guide 2'nd edition
3      Brent    Welch     Practical Programming in Tcl/Tk
4      Michael  McClennan Effective Tcl/Tk Programming
5      Don      Libes     Exploring Expect
</CODE></PRE>

<P>

The dict would look like this:
<PRE><CODE>
1 {first clif last flynt title {Tcl/Tk For Real Programmers}}
2 {first clif last flynt title {Tcl/Tk: A Developer's Guide}}
...
</CODE></PRE>

The keys are <CODE>1,2,3,4,</CODE>and </CODE>5</CODE>, and the
value is another dict.  Each set of values is 
is a dict in which the keys are <CODE>first, last,</CODE> and
<CODE>title</CODE>.

<P>
The <CODE>dict set</CODE> command can be used to assign nested values.
<P>

When <CODE>dict set</CODE> is evaluated with multiple values they
represent successively nested key/key/.../value pairs.

<PRE><CODE>
#>  dict set test a 1 b 2 c 3
<B>a {1 {b {2 {c 3}}}}</B>
</CODE></PRE>

<P>
You can create the book data either:
<UL>
  <LI> Successive set commands to add data:
  <PRE><CODE>
    dict set books 1 first Clif
    dict set books 1 last  Flynt
    ...
  </CODE></PRE>
  <LI> append data as a list:
  <PRE><CODE>
     dict set books 2 {first clif last flynt title "Tcl/Tk: A Developers Guide"}
     ...
  </CODE></PRE>
</UL>
<P>
  You can iterate through a list with the <CODE>dict for</CODE> and
code <CODE>dict with</CODE>
<P>
  <DL>
    <BR><DT><CODE>dict for <I>{keyVar valVar} $dictData {script} </I></CODE>
    <DD>Iterate through the list assigning keys to the <CODE>keyVar</CODE> and
    the associated values  to the <CODE>valVar</CODE>.  The contents of the
    <CODE>keyVar</CODE> and <CODE>valVar</CODE> are available to the script.

    <BR><DT><CODE>dict with<I> varName {script}</I></CODE>
    <DD>Assign values to variables named for the keys in the variable
    <CODE>varName</CODE> and evaluate <CODE>script</CODE>.  This may create
    or modify local variables.  The variables named for the keys will
    have the final value after evaluating the <CODE>script</CODE>
  </DL>

The <CODE>dict for</CODE> and <CODE>dict with</CODE> commands are 
commonly used together, as shown in the examples.
:TEXT_END:

:CODE_START:

puts " dict set test a 1 b 2 c 3 returns:"
puts [dict set test a 1 b 2 c 3]
puts "The value associated with 'a' is: [dict get $test a]"
puts "The value associated with 'a 1' is: [dict get $test a 1]\n"

dict set books 1 first Clif
dict set books 1 last Flynt
dict set books 1 title "Tcl/Tk For Real Programmers"

dict set books 2 [list first Clif \
    last Flynt \
    title "Tcl/Tk: A Developers Guide"]

foreach {id first last title} {
    3      Brent    Welch     {Practical Programming in Tcl/Tk}
    4      Michael  McClennan {Effective Tcl/Tk Programming}
    5      Don      Libes     {Exploring Expect}  } {
  dict set books $id [list first $first last $last title $title]
}

set first firstTest
dict for {id info} $books {
  dict with info {
    puts "$id: $last,$first  \"$title\""
  }
}
puts "after dict for: first is $first"

:TEXT_END:

