LINUX.ORG.RU

tcl, append к последнему элементу списка


0

0

Вот, изучая тикль, наваял тут такой скрипт:

set example {a b {ca cb cc} {da {dba dbb} dc {dda ddb ddc}}}

proc insertAtDepth {listtarget listtoinsert depth} { if {$depth == 1} { return [concat $listtarget $listtoinsert] } return [lappend [subtract $listtarget] [insertAtDepth [pop $listtarget] $listtoinsert [expr $depth - 1]]] }

proc pop {listarg} { return [lindex $listarg end] }

proc subtract {listarg} { return [lrange $listarg 0 end-1] }

puts [insertAtDepth $example f 2]

По идее, insertAtDepth должна приписывать к последнему элементу списка, который находится на глубине вложенности depth, свой второй аргумент. Однако, работает она не так, как ожидается: почему-то в рекурсии теряется начало списка :(

Помогите, плз, понять -- в чем тут проблема.

anonymous

Честно говоря, лень было разбираться, поэтому по ТЗ накатал свой вариант:

set example {a b {ca cb cc} {da {dba dbb} dc {dda ddb ddc}}}

proc insertAtDepth {target ins depth} {
if { $depth == 1 } {
return [ concat $target $ins ]
} else {
set res ""
foreach sub $target {
lappend res [ insertAtDepth $target $ins [ expr $depth - 1 ] ]
}
return $res
}
}

puts [ insertAtDepth $example {jopa kaka} 2 ]

gaa ★★
()
Ответ на: комментарий от gaa

Или тебе надо добавить не к листу на заданной глубине, а именно к его последнему элементу? Тогда надо заменить return [ concat $target $ins ] на return [ concat [ lrange $target 0 end-1 ] [ list [ lindex $target end ] ] $ins ]

Вот функция , в которой я поправил один промах и сделал на выбор оба варианта

proc insertAtDepth {target ins depth} {
if { $depth == 1 } {
# return [ concat $target $ins ]
return [ concat [ lrange $target 0 end-1 ] [ list [ lindex $target end ] ] $ins ]
} else {
set res ""
foreach sub $target {
lappend res [ insertAtDepth $sub $ins [ expr $depth - 1 ] ]
}
return $res
}
}

gaa ★★
()
Ответ на: комментарий от gaa

Спасибо, но это немного не то, что я хотел :)

Твой скрипт добавляет элемент ко всем элементам на глубине не больше заданной, а мне надо, чтобы только к последнему..

Буду грызть дальше.

anonymous
()

А так пойдет?

set example {a b {ca cb cc} {da {dba dbb} dc {dda ddb ddc}}}

proc insertAtDepth {listtarget listtoinsert depth} {
 set ltmp {}
 for {set i 0} {$i < $depth} {incr i} {lappend ltmp end}
 lset listtarget $ltmp [concat [lindex $listtarget $ltmp] $listtoinsert]
 }

puts [insertAtDepth $example f 2]

anonymous
()
Ответ на: комментарий от anonymous

> Твой скрипт добавляет элемент ко всем элементам на глубине не больше заданной, а мне надо, чтобы только к последнему..

Ну значит я как-то не так понял ТЗ :) если объяснишь -- попробую переписать

gaa ★★
()
Ответ на: комментарий от anonymous

set example {a b {ca cb cc} {da {dba dbb} dc {dda ddb ddc}}}

proc insertAtDepth {listtarget listtoinsert depth} { set ltmp {} for {set i 0} {$i < $depth} {incr i} {lappend ltmp end} lset listtarget $ltmp [concat [lindex $listtarget $ltmp] $listtoinsert] }

puts [insertAtDepth $example f 2]

Мой тикль не понимает lset :(

Сформулирую, что мне нужно.

Пусть дан список, элементами которого часто являются другие списки такого же типа, то есть тоже с подсписками и так далее. Необходимо вставить заданный элемент в конец последнего на данной глубине списка. Пусть глубина начинается с 1.То есть:

список {a b c {d e} f} после insertAtDepth(список элемент 2) должен стать таким: {a b c {d e элемент} f}

или

сипсок {a b c {d e {1 2}} f} после insertAtDepth(список элемент 2) должен стать таким: {a b c {d e {1 2} элемент} f}

после insertAtDepth(список элемент 3) должен стать таким: {a b c {d e {1 2 элемент}} f}

anonymous
()
Ответ на: комментарий от anonymous

> Пусть дан список, элементами которого часто являются другие списки такого же типа, то есть тоже с подсписками и так далее. Необходимо вставить заданный элемент в конец последнего на данной глубине списка. Пусть глубина начинается с 1.То есть:

> список {a b c {d e} f} после insertAtDepth(список элемент 2) должен стать таким: {a b c {d e элемент} f}

Это невозможно в общем случае: Для того, чтобы сделать указанное тобой, надо уметь различать списки и текст, чего тикль принципиально не умеет, так как у него список -- это набор слов, раздёлённых пробельными символами.

Потому: a "a" {a} [ list a ] [ list "a" ] [ list {a} ] -- это одна и та же строка, соcтоящая из одной буквы "a".

gaa ★★
()
Ответ на: комментарий от gaa

> Потому: a "a" {a} [ list a ] [ list "a" ] [ list {a} ] -- это одна и та же строка, соcтоящая из одной буквы "a".

И даже [ list [ list [ list [ list a ] ] ] ] !

gaa ★★
()
Ответ на: комментарий от gaa

Спасибо. Отрицательный результат, тоже результат. :)

anonymous
()

Если примем в качестве упрощения, что список - это то, что в фигурных скобочках :) , то можно сделать очень просто:

set example {a b {ca cb cc} {da {dba dbb} dc {dda ddb ddc}}}
proc InsertAtDepth {lIn element depth} {
 set l [string length $lIn]
 incr l -1
 set BraceCount 1
 while {$l >= 0} {
  switch -exact [string index $lIn $l] {
   \} {incr BraceCount}
   \{ {incr BraceCount -1}
   }
  if {$BraceCount == $depth} {
   return [string range $lIn 0 [expr $l - 1]]\ [set element][string range $lIn $l end]
   }
  incr l -1
  }
 }
puts [InsertAtDepth $example элемент 2]

P.S. lset появился в версии 8.4, а сейчас уже альфу 8.6 гоняют, так что срочно обновлять хотя бы до 8.5, оно того стОит, серьезно ...

anonymous
()
Ответ на: комментарий от anonymous

> Если примем в качестве упрощения, что список - это то, что в фигурных скобочках :) , то можно сделать очень просто:

Это весьма багоопасное упрощение:

puts [ list "hello, world!" {golakteko opasnoste} [ list eto hren so ckobkami \} ] "}" "{" ]
{hello, world!} {golakteko opasnoste} {eto hren so ckobkami \}} \} \{

gaa ★★
()
Ответ на: комментарий от gaa

> Это весьма багоопасное упрощение:

Само собой разумеется, просто эту ситуацию надо специально учесть в том случае, если автор темы не исключает возможность наличия в исходных данных хренов со скобками :) А вот как это сделать - давайте оставим в качестве упражнения автору темы. Возможный hint: [string map]

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.