table

Difference between version 24 and 25 - Previous - Next
A '''table''' is a data layout that presents data as rows and columns.  Well
suited to human interpretation, tables have been in use for thousands of years
to visually represent data.  The earliest-known tables date back to the fourth
millenium B.C., and are among the earliest known examples of writing.



** See also **

   [Displaying tables]:   
   [grid]:   a layout manager based on the '''table''' concept.
   [dictionary]:   A "dictionary" or "matrix" is used when referring to a data structure that holds tabular data and look up by key value.
   [matrix]:   
   [Multicolumn listbox]:   used when referring to layout multi-dimensional data in tabular way.
   [nested list]:   :new
   [record]:   
   [spreadsheet]:   
   [Sqawk]:      [TclRal]:   an implementation of Relational Algebra
   [Tktable]:   
   [tbmerge]:   
   [Tables]:   
**   [TclRal]:   aIn implementatiron of Relaductional Algebra**
[Richard Suchenwirth] 2002-12-06 - Tables are understood here as rectangular (matrix) arrangements of data in rows (one row per "item"/"record") and columns (one column per "field"/"element"). They are for instance the building blocks of relational databases and spreadsheets. In Tcl, a sensible implementation for [compact data storage] would be as a list of lists. This way, they are "pure values" and can be passed e.g. through functions that take a table and return a table. No con-/destructors are needed, in contrast to the heavierweight [matrix]: in [Tcllib]. I know there are many table implementations in Tcl, but like so often I wanted to build one "with my bare hands" and as simple as possible. As you see below, many functionalities can be "implemented" by just using Tcl's list functions.
A nice table [also has a ''header line'', that specifies the field names. So to create such a table with a defined field structure, but no contents yet, one just assigns the header list:
 set tbl {{firstname lastname phone}}
Note the double bracing, which makes sure ''tbl'' is a 1-element list. Adding "records" to the table is as easy as
 lappend tbl {John Smith (123)456-7890}
Make sure the fields (cells) match those in the header. Here single bracing is correct. If a field content contains spaces, it must be quoted or braced too:
 lappend tbl {{George W} Bush 234-5678}
Sorting a table can be done with lsort -index, taking care that the header line stays on top:
 proc tsort args {
    set table [lindex $args end]
    set header [lindex $table 0]
    set res [eval lsort [lrange $args 0 end-1] [list [lrange $table 1 end]]]
    linsert $res 0 $header
 }
Removing a row (or contiguous sequence of rows) by numeric index is a job for [lreplace]:
 set tbl [lreplace $tbl $from $to]
Simple printing of such a table, a row per line, is easy with
 puts [join $tbl \n]
Accessing fields in a table is more fun with the field names than the numeric indexes, which is made easy by the fact that the field names are in the first row:
 proc t@ {tbl field} {lsearch [lindex $tbl 0] $field}
 % t@ $tbl phone
 2
You can then access cells:
 puts [lindex $tbl $rownumber [t@ $tbl lastname]]
and replace cell contents like this:
 lset tbl $rownumber [t@ $tbl phone] (222)333-4567
Here is how to filter a table by giving pairs of field name and glob-style expression - in addition to the header line, all rows that satisfy at least one of those come through (you can force AND behavior by just nesting such calls):
 proc trows {tbl args} {
    set conditions {}
    foreach {field condition} $args {
        lappend conditions [t@ $tbl $field] $condition
    }
    set res [list [lindex $tbl 0]]
    foreach row [lrange $tbl 1 end] {
        foreach {index condition} $conditions {
            if [string match $condition [lindex $row $index]] {
               lappend res $row
               break; # one hit is sufficient
            }
        }
    }
    set res
 }
 % trows $tbl lastname Sm*
 {firstname lastname} phone {John Smith (123)456-7890}
This filters (and, if wanted, rearranges) columns, sort of what is called a "view":
 proc tcols {tbl args} {
    set indices {}
    foreach field $args {lappend indices [t@ $tbl $field]}
    set res {}
    foreach row $tbl {
        set newrow {}
        foreach index $indices {lappend newrow [lindex $row $index]}
        lappend res $newrow
    }
    set res
 }


** Resources **
   * [http://csis.pace.edu/~marchese/Papers/IV11/Marchese_IV%2711.pdf%|%Exploring the Origins of Tables for Information Visualization] ,Francis T. Marchese ,2011
   * [http://www.metmuseum.org/toah/hd/wrtg/hd_wrtg.htm%|%The Origins of Writing], the Heilbrunn Timeline of Art History
   [http://www.metmuseum.org/toah/hd/wrtg/hd_wrtg.htm%|%The Origins of Writing], the Heilbrunn Timeline of Art History:   


** Misc **

2001-02-23:   So, where is the code from [RS] that was used to pretty-printing a list of lists?

[PYK] 2014-01-01:   It was moved to [dictionary].

<<categories>> Category Discussion | CTatblegory | Widget