the_meter413
the_meter413

Reputation: 299

Tcl/Tk: How do I append or insert into a nested list?

I have two lists - each containing nested lists - that I want to combine into a third list.

When I try to use lappend as follows, my new list only contains the elements from my second list, and none of the elements from the first list.

% set list1 {{a b c} {d e f} {g h i}}
{a b c} {d e f} {g h i}
% set list2 {{j k l} {m n o} {p q r}}
{j k l} {m n o} {p q r}
% set list3 [lappend [lindex $list1 0] [lindex $list2 0]]
{j k l}

I was hoping this would return

{a b c j k l}

Similarly when I try to use linsert, I get a "bad index" error:

% set list3 [linsert [lindex $list1 0] [lindex $list2 0]]
bad index "j k l": must be integer?[+-]integer? or end?[+-]integer?

Any thoughts?

Ideally, I'd like to take my two lists, and iterate through each nested list so that my output yields

{a b c j k l} {d e f m n o} {g h i p q r}

Upvotes: 2

Views: 5888

Answers (4)

Varinder Singh
Varinder Singh

Reputation: 1

Another way to do this is -

% set list1 {{a b c} {d e f} {g h i}}
{a b c} {d e f} {g h i}
% set list2 {{j k l} {m n o} {p q r}}
{j k l} {m n o} {p q r}
% lappend list3 "[lindex $list1 0] [lindex $list2 0]"
{a b c j k l}

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 246799

with linsert you would write:

set joined [linsert [lindex $list1 0] end {*}[lindex $list2 0]]  ;# => a b c j k l

We're specifying we want to insert, at the end of the first element of list1, the elements of the first element of list2

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137567

Tcl 8.6 has an operation that lets you lappend one element directly into a nested list:

lset theListVariable $index end+1 $theItemToAdd

For example (interactive session):

% set lst {a b c d}
a b c d
% lset lst 1 end+1 e
a {b e} c d
% lset lst 1 end+1 f
a {b e f} c d

That means we'd do your overall operation like this:

set list3 $list1
set index 0
foreach sublist $list2 {
    foreach item $sublist {
        lset list3 $index end+1 $item
    }
    incr index
}

Or, more likely through concatenation:

set list3 [lmap a $list1 b $list2 {
   list {*}$a {*}$b
}]

The use of list with expansion of all arguments does list concatenation. You could use concat instead, but that sometimes doesn't do list concat (for complicated backward compatibility reasons).

Upvotes: 1

Brad Lanam
Brad Lanam

Reputation: 5723

The lappend command takes as its first argument a list variable name. You are passing it the name {a b c}.

You can use the concat command to join two lists together to create a single list.

set list3 [concat [lindex $list1 0] [lindex $list2 0]]

Or create a new list with list and expansion:

set list3 [list {*}[lindex $list1 0] {*}[lindex $list2 0]]

To iterate through the lists, you can use:

foreach {item1} $list1 {item2} $list2 {
   ...
}

Upvotes: 2

Related Questions