Tcl/Tk: как добавить или вставить во вложенный список?

У меня есть два списка, каждый из которых содержит вложенные списки, которые я хочу объединить в третий список.

Когда я пытаюсь использовать lappend следующим образом, мой новый список содержит только элементы из моего второго списка и ни один из элементов из первого списка.

% 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}}
extra characters after close-brace
% 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}

Я надеялся, что это вернется

{a b c j k l}

Точно так же, когда я пытаюсь использовать linsert, я получаю ошибку «плохой индекс»:

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

Какие-нибудь мысли?

В идеале я хотел бы взять свои два списка и перебрать каждый вложенный список, чтобы мой вывод давал

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

person the_meter413    schedule 05.12.2018    source источник


Ответы (3)


Команда lappend принимает в качестве первого аргумента имя переменной списка . Вы передаете ему имя {a b c}.

Вы можете использовать команду concat, чтобы объединить два списка, чтобы создать единый список.

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

Или создайте новый список с списком и расширением:

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

Для перебора списков вы можете использовать:

foreach {item1} $list1 {item2} $list2 {
   ...
}
person Brad Lanam    schedule 06.12.2018
comment
Есть ли преимущество использования concat по сравнению с set list3 "[lindex $list1 0] [lindex $list2 0]"? - person Brandin; 14.01.2019

В Tcl 8.6 есть операция, которая позволяет вам lappend один элемент напрямую попасть во вложенный список:

lset theListVariable $index end+1 $theItemToAdd

Например (интерактивный сеанс):

% 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

Это означает, что мы будем выполнять вашу общую операцию следующим образом:

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

Или, что более вероятно, через конкатенацию:

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

Использование list с раскрытием всех аргументов приводит к объединению списков. Вместо этого вы можете использовать concat, но иногда это не приводит к списку concat (по сложным причинам обратной совместимости).

person Donal Fellows    schedule 06.12.2018
comment
Мне нравится последний бит с использованием lmap. К сожалению для меня, мое приложение использует Tcl 8.4, и, похоже, lmap не является функцией в этой версии Tcl. Предложение concat в ответе другого респондента, похоже, работает, но мне любопытен ваш комментарий о том, что concat имеет проблемы с обратной совместимостью? Можете ли вы уточнить? Спасибо за помощь! - person the_meter413; 06.12.2018

с linsert вы должны написать:

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

Мы указываем, что хотим вставить в конец первого элемента списка1 элементы первого элемента списка2

person glenn jackman    schedule 06.12.2018