Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to lappend to nested dicts?

1,153 views
Skip to first unread message

Georgios Petasis

unread,
Jul 19, 2012, 2:07:16 PM7/19/12
to
Hi all,

I was looking the dict manual, and I realised that it is very easy to
create nested directories (with dict set), but is not so easy to lappend
values to nested dictionaries.

For example:

dict set d person name phone_numbers 1

returns a dict with nested dictionaries:

person {name {phone_numbers 1}}

But what is the most efficient way to append a new phone number to the
last dict?

Initially I thought that the following would work:

dict lappend d person name phone_numbers 2

But it does not. What is the best alternative?

(From the manual I am not sure that I understood what dict update & dict
with are supposed to do. I am totally lost with the examples.)

George

Georgios Petasis

unread,
Jul 19, 2012, 2:17:13 PM7/19/12
to
Is the following the most efficient way to lappend items to a nested dict?

set d [dict create]

set id 0
foreach name {petasis petasis petasis} {
if {[dict exists $d person $name]} {
dict with d person {
lappend $name [incr id]
}
} else {
dict set d person $name [list [incr id]]
}
}
puts $d

Because I need to do this for about 500.000 items...

George

Harald Oehlmann

unread,
Jul 20, 2012, 3:30:35 AM7/20/12
to
Hi Heorge,

I have tried it, but my knowledge is not sufficient, sorry.
Here are the traces:
http://wiki.tcl.tk/19938
Feel free to edit.
-Harald

Ben Collver

unread,
Jul 20, 2012, 10:00:30 AM7/20/12
to
On Thursday, July 19, 2012 11:07:16 AM UTC-7, Georgios Petasis wrote:
> Hi all,
>
> I was looking the dict manual, and I realised that it is very easy to
> create nested directories (with dict set), but is not so easy to lappend
> values to nested dictionaries.
>
> For example:
>
> dict set d person name phone_numbers 1
>
> returns a dict with nested dictionaries:
>
> person {name {phone_numbers 1}}
>
> But what is the most efficient way to append a new phone number to the
> last dict?
>
> Initially I thought that the following would work:
>
> dict lappend d person name phone_numbers 2
>
> But it does not. What is the best alternative?
>
> (From the manual I am not sure that I understood what dict update & dict
> with are supposed to do. I am totally lost with the examples.)
>
> George


proc dict_klappened {dictVar args} {
if {[llength $args] < 2} {
error "wrong # args: should be \"klappened dictVar key ?key ...? value\""
}
upvar $dictVar that
if {[llength $args] == 2} {
set key [lindex $args end-1]
set value [lindex $args end]
dict lappend that $key $value
} else {
set key [lindex $args 0]
set argz [lrange $args 1 end]
dict with that {
dict_klappened $key {*}$argz
}
}
}

dict set d person name phone_numbers 1
dict_klappened d person name phone_numbers 2
Message has been deleted

Emiliano

unread,
Jul 24, 2012, 1:56:46 PM7/24/12
to
On Thursday, July 19, 2012 3:07:16 PM UTC-3, Georgios Petasis wrote:
> Hi all,
>
> I was looking the dict manual, and I realised that it is very easy to
> create nested directories (with dict set), but is not so easy to lappend
> values to nested dictionaries.
>
> For example:
>
> dict set d person name phone_numbers 1
>
> returns a dict with nested dictionaries:
>
> person {name {phone_numbers 1}}
>
> But what is the most efficient way to append a new phone number to the
> last dict?
>
> Initially I thought that the following would work:
>
> dict lappend d person name phone_numbers 2
>
> But it does not. What is the best alternative?
>
> (From the manual I am not sure that I understood what dict update &amp; dict
> with are supposed to do. I am totally lost with the examples.)


Since [dict] is an ensemble command, you can easily add your own
subcommand to [lappend] to nested dictionaries.
The following version uses [dict with]:

proc ::tcl::dict::lappend2 {dict args} {
upvar 1 $dict d
with d {*}[lrange $args 0 end-2] {
::lappend [lindex $args end-1] [lindex $args end]
}
}
namespace ensemble configure dict -map \
[dict merge [namespace ensemble configure dict -map] \
{lappend2 ::tcl::dict::lappend2}]


testing:

% dict set d person name phone_numbers 1
person {name {phone_numbers 1}}
% dict lappend2 d person name phone_numbers 2
1 2
% set d
person {name {phone_numbers {1 2}}}

Regards
Emiliano
0 new messages