Home > Archive > Tcl > November 2006 > arrays in arrays?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
|
| In PERL I can put arrays in arrays.
my @array1 = ('val1', 'val2', 'val3');
my @array2 = ( \@array1 );
In TCL I'm trying
set arr1(key1) val1
set arr1(key2) val2
set arr1(key3) val3
set arr2(key4) $arr1
Tclsh rightfully complains that $arr1 is a scalar and not
an array. How do I set an array as the value in another array?
Mike
| |
| suchenwi 2006-11-29, 7:08 pm |
|
Mike schrieb:
> In PERL I can put arrays in arrays.
>
> my @array1 = ('val1', 'val2', 'val3');
> my @array2 = ( \@array1 );
>
> In TCL I'm trying
>
> set arr1(key1) val1
> set arr1(key2) val2
> set arr1(key3) val3
>
> set arr2(key4) $arr1
>
> Tclsh rightfully complains that $arr1 is a scalar and not
> an array. How do I set an array as the value in another array?
>
In Tcl, arrays are collections of variables which cannot be nested. You
can however dump an array into a list value with [array get] and store
that as element of another array.
If you have Tcl 8.5 or the dict extensions, "dicts" are what you want -
pure-value maps that can be nested to arbitrary depth. Except for
element traces, they provide all that arrays do.
| |
| Robert Heller 2006-11-29, 7:08 pm |
| At Wed, 29 Nov 2006 13:38:19 GMT Mike <mikee@mikee.ath.cx> wrote:
>
> In PERL I can put arrays in arrays.
>
> my @array1 = ('val1', 'val2', 'val3');
> my @array2 = ( \@array1 );
>
> In TCL I'm trying
>
> set arr1(key1) val1
> set arr1(key2) val2
> set arr1(key3) val3
>
> set arr2(key4) $arr1
>
> Tclsh rightfully complains that $arr1 is a scalar and not
> an array. How do I set an array as the value in another array?
Two things:
1) Tcl arrays are not what a traditional language would call an array. A
Tcl array is NOT a sequence of numerically indexable elements. It is an
association table.
2) Tcl arrays are stored as the value object in the same way as other
Tcl values (numbers, strings, lists, etc.).
You are going to have to store the array by *name*, not by value:
set arr1(key1) val1
set arr1(key2) val2
set arr1(key3) val3
set arr2(key4) arr1
later:
upvar $arr2(key4) localarray
puts $localarray(key1)
Note that things are tricky WRT scope rules!
>
> Mike
>
--
Robert Heller -- 978-544-6933
Deepwoods Software -- Linux Installation and Administration
http://www.deepsoft.com/ -- Web Hosting, with CGI and Database
heller@deepsoft.com -- Contract Programming: C/C++, Tcl/Tk
| |
| Glenn Jackman 2006-11-29, 7:08 pm |
| At 2006-11-29 08:38AM, "Mike" wrote:
> In PERL I can put arrays in arrays.
>
> my @array1 = ('val1', 'val2', 'val3');
> my @array2 = ( \@array1 );
>
> In TCL I'm trying
>
> set arr1(key1) val1
> set arr1(key2) val2
> set arr1(key3) val3
>
> set arr2(key4) $arr1
>
> Tclsh rightfully complains that $arr1 is a scalar and not
> an array. How do I set an array as the value in another array?
Two dimensional arrays in Tcl are often accomplished by "combining" the
keys -- joining them with a comma typically. For example:
array set arr2d {
a,c 1
a,d 2
b,c 3
b,d 4
}
Or, in your case above:
array set arr2 {
key4,key1 val1
key4,key2 val2
key4,key3 val3
}
--
Glenn Jackman
Ulterior Designer
| |
|
| On 2006-11-29, Glenn Jackman <glennj@ncf.ca> wrote:
> At 2006-11-29 08:38AM, "Mike" wrote:
>
> Two dimensional arrays in Tcl are often accomplished by "combining" the
> keys -- joining them with a comma typically. For example:
>
> array set arr2d {
> a,c 1
> a,d 2
> b,c 3
> b,d 4
> }
>
> Or, in your case above:
> array set arr2 {
> key4,key1 val1
> key4,key2 val2
> key4,key3 val3
> }
>
Thanks for the replies. The above approach works for what I need.
I am adding complex keys to the tcl array in the form:
set arr(file,$file,section,$section,key,$key
) $value
Mike
| |
| Darren New 2006-11-29, 7:08 pm |
| Mike wrote:
> set arr(file,$file,section,$section,key,$key
) $value
You don't really need the literals, there.
arr($file,$section,$key)
will probably do you just fine, unless there's some other processing
going on (such as also looking for arr(section,$section,...)
--
Darren New / San Diego, CA, USA (PST)
Scruffitarianism - Where T-shirt, jeans,
and a three-day beard are "Sunday Best."
| |
| Glenn Jackman 2006-11-29, 7:08 pm |
| At 2006-11-29 10:48AM, "Mike" wrote:
> I am adding complex keys to the tcl array in the form:
>
> set arr(file,$file,section,$section,key,$key
) $value
I would suggest you don't need the keywords there -- this should suffice:
set arr($file,$section,$key) $value
--
Glenn Jackman
Ulterior Designer
| |
| Glenn Jackman 2006-11-29, 7:08 pm |
| At 2006-11-29 10:48AM, "Mike" wrote:
> I am adding complex keys to the tcl array in the form:
>
> set arr(file,$file,section,$section,key,$key
) $value
I would suggest you don't need the keywords there -- this should suffice:
set arr($file,$section,$key) $value
Then, to later process the array:
foreach name [array names arr] {
set value $arr($name)
foreach {file section key} [split $name ,] break
# ... do stuff
}
--
Glenn Jackman
Ulterior Designer
| |
| Glenn Jackman 2006-11-29, 7:08 pm |
| At 2006-11-29 11:37AM, "Glenn Jackman" wrote:
> foreach {file section key} [split $name ,] break
And to be complete, in Tcl 8.5 this would be
lassign [split $name ,] file section key
--
Glenn Jackman
Ulterior Designer
| |
| Robert Heller 2006-11-29, 7:08 pm |
| At 29 Nov 2006 16:35:04 GMT Glenn Jackman <glennj@ncf.ca> wrote:
>
> At 2006-11-29 10:48AM, "Mike" wrote:
>
> I would suggest you don't need the keywords there -- this should suffice:
>
> set arr($file,$section,$key) $value
Unless the values for $file, $section, or $key interset with each other
-- that is if there is some ambiguousness going on.
>
--
Robert Heller -- 978-544-6933
Deepwoods Software -- Linux Installation and Administration
http://www.deepsoft.com/ -- Web Hosting, with CGI and Database
heller@deepsoft.com -- Contract Programming: C/C++, Tcl/Tk
| |
| suchenwi 2006-11-29, 7:08 pm |
|
Robert Heller schrieb:
>
> Unless the values for $file, $section, or $key interset with each other
> -- that is if there is some ambiguousness going on.
Intersection between these domains is no problem, as the domain is
evident by the position in the comma-separated string. Trouble is only
to be expected if file, section or key may contain commas. The
separator can be chosen freely and best should not occur in any of the
data.
| |
| Glenn Jackman 2006-11-29, 7:08 pm |
| At 2006-11-29 12:06PM, "Robert Heller" wrote:
> At 29 Nov 2006 16:35:04 GMT Glenn Jackman <glennj@ncf.ca> wrote:
>
> Unless the values for $file, $section, or $key interset with each other
> -- that is if there is some ambiguousness going on.
What's ambiguous? The programmer knows that the first comma-delimited
substring is the file, the second is the section and the third is the
key. Even if $file == $section == $key, there is no confusion.
The only trouble would arise if $file or $section contained commas.
--
Glenn Jackman
Ulterior Designer
| |
| Darren New 2006-11-29, 7:08 pm |
| Robert Heller wrote:
>
> Unless the values for $file, $section, or $key interset with each other
No, because they'd still be in order. The ambiguity would be if $file,
$section, or $key had a comma in it. Of course, if $file ended in
",section,", you would be in trouble in the old system too. :-)
Wouldn't
set arr([list $file $section $key]) $value
work and be unambiguous?
--
Darren New / San Diego, CA, USA (PST)
Scruffitarianism - Where T-shirt, jeans,
and a three-day beard are "Sunday Best."
| |
| Gerald W. Lester 2006-11-29, 7:08 pm |
| In-Reply-To: <Okjbh.32666$Fg.8555@tornado.socal.rr.com>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Lines: 22
Message-ID: <Qnjbh.316$Gf6.45@newsfe21.lga>
Date: Wed, 29 Nov 2006 11:25:01 -0600
NNTP-Posting-Host: 24.252.109.162
X-Complaints-To: admin@cox.net
X-Trace: newsfe21.lga 1164821104 24.252.109.162 (Wed, 29 Nov 2006 10:25:04 MST)
NNTP-Posting-Date: Wed, 29 Nov 2006 10:25:04 MST
Organization: Cox
Xref: number1.nntp.dca.giganews.com comp.lang.tcl:273108
Darren New wrote:
> Robert Heller wrote:
>
> No, because they'd still be in order. The ambiguity would be if $file,
> $section, or $key had a comma in it. Of course, if $file ended in
> ",section,", you would be in trouble in the old system too. :-)
>
> Wouldn't
> set arr([list $file $section $key]) $value
> work and be unambiguous?
>
Yes
--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+
| |
| Donald Arseneau 2006-11-29, 7:08 pm |
| Mike <mikee@mikee.ath.cx> writes:
> In PERL I can put arrays in arrays.
>
> my @array1 = ('val1', 'val2', 'val3');
> my @array2 = ( \@array1 );
It looks like people mentioned the dichotomy, but only recommended
dict and array solutions....
Perl "arrays" are called "lists" in Tcl. Tcl "arrays" are called "hashes"
in Perl.
So use lists! Lists can be nested
set a1 [list "val1" "val2" "val3"]
or
set a1 {val1 val2 val3}
set a2 [list $a1]
Now $a2 is a list with one element, and that element is a list with three
elements. You can perform lookup and settings dorectly in this nested list
set v [lindex $a2 0 1]
gives $v the value "val2"
lset a2 0 2 "valend"
modifies a2 so it is {{val1 val2 valend}}
--
Donald Arseneau asnd@triumf.ca
| |
| slebetman@yahoo.com 2006-11-29, 10:03 pm |
| Mike wrote:
> On 2006-11-29, Glenn Jackman <glennj@ncf.ca> wrote:
>
> Thanks for the replies. The above approach works for what I need.
> I am adding complex keys to the tcl array in the form:
>
> set arr(file,$file,section,$section,key,$key
) $value
Like someone else mentioned in this thread, what you really want is a
list(array) not an array(hash) (perlspeak in brackets). But since
you're going down this path, and if you heed the advice to use the
simpler:
arr($file,$section,$key)
then I'd like to highlight a "feature" of Tcl's implementation of
hashes *ahem* arrays..
The [array get] command does glob matching by default. People often
overlook this but it is a very powerful thing. Say for example you want
to get all values of all sections of a file. Simply do:
set x [array get arr $file,*,*]
or say for example you want to process section 1 from all files, simply
do:
foreach {compoundKey val} [array get arr *,1,*] {
# processing here
}
| |
| Fredderic 2006-11-30, 4:16 am |
| On 29 Nov 2006 09:10:23 -0800,
"suchenwi" <richard.suchenwirth-bauersachs@siemens.com> wrote:
> Intersection between these domains is no problem, as the domain is
> evident by the position in the comma-separated string. Trouble is only
> to be expected if file, section or key may contain commas. The
> separator can be chosen freely and best should not occur in any of the
> data.
If there's any concern with the keys containing the separator
character, then use the one character they can't contain; a first-level
word break. Just wrap them in [list] first;
set arr([list $file $section $key]) $value
[list] will take care of any uglyness (except the way it looks). Or to
make it a little more legible, I often represent that kind of thing on
two lines;
set key [list $file $section $key]
set arr($key) $value
I've used this technique in cases where I had no control over the
content of the keys, or in one case, even the number of keys. I
believe it'll even work when using binary data as keys.
Fredderic
|
|
|
|
|