Многоуровневый словарь TCL - как обновить тот же ключ, добавив к нему - PullRequest
1 голос
/ 03 марта 2020

У меня есть диктат под названием test, я буду sh итеративно обновлять тот же ключ, добавляя в него новые элементы. Поэтому в конечном итоге это будет выглядеть так:

AIM

test {
1 {flps {o1 o2 o3 ...}}
}

Какой стандартный способ сделать это ? У меня есть код ниже прямо сейчас:

set test [dict create] ;
dict set test 1 "flps" "o1"   ;  #### first value o1 added
set new "[dict get $test 1 regs] o2" ; ##temp variable that append the old + new value
dict set test 1 regs $new         ; ### does dict set overwrite ? 

Ответы [ 3 ]

0 голосов
/ 03 марта 2020

На основании ссылки mrcalvin - нашло, что это работает

% set d {key1 {key2 value1}}
% dictlappendsub d key1 key2 value2
key1 {key2 {value1 value2}}
% dictlappendsub d key1 key3 value3
key1 {key2 {value1 value2} key3 value3}

Этого можно достичь:

# dictlappendsub dict key1 ... keyn value
proc dictlappendsub {dictName args} {
    upvar 1 $dictName d
    set keys [lrange $args 0 end-1]
    if {[dict exists $d {*}$keys]} {    ; **## What does this do!? WOW**
        dict set d {*}$keys [linsert [dict get $d {*}$keys] end [lindex $args end]]
    } else {
        dict set d {*}$keys [lrange $args end end]
    }
}
0 голосов
/ 04 марта 2020

Стандартных команд для этого не существует, потому что число возможных команд для всех различных вещей, которые могут быть выполнены, становится слишком большим; для вас предусмотрены только общие случаи (точный выбор частично зависит от того, что является технически однозначным, учитывая, что словари Tcl допускают произвольные значения в качестве ключей по схеме ). Вместо этого dict update и dict with предоставляются в качестве инструментов, позволяющих людям самим создавать свои решения.

В частности, делая предположение , что мы добавляем ровно один элемент списка и с dict update, upvar и некоторой рекурсией, мы можем сделать это:

proc dict_lappend_item {dictVar args} {
    upvar 1 $dictVar d
    if {[llength $args] == 1} {
        lappend d [lindex $args 0]
    } else {
        set args [lassign $args key]
        dict update d $key inner {
            dict_lappend_item inner {*}$args
        }
    }
    return $d
}

Вот как это использовать:

% set test [dict create]
% dict set test 1 "flps" "o1"
1 {flps o1}
% dict_lappend_item test 1 flps o2
1 {flps {o1 o2}}
% dict_lappend_item test 1 flps o3
1 {flps {o1 o2 o3}}

Похоже, что это делать то, что вам нужно. (Обратите внимание, что dict lappend не делает этого предположения; вместо этого он обрабатывает случай добавления-множественных элементов, который имеет некоторые истинные проблемы производительности, если не обрабатывать это специально в C коде.)


Вы можете подключить описанную выше процедуру к dict.

set map [namespace ensemble configure dict -map]
dict set map additem ::dict_lappend_item
namespace ensemble configure dict -map $map

, а затем можете сделать:

% dict additem test 1 flps o4
1 {flps {o1 o2 o3 o4}}

Осторожнее, если вы сделаете это. Возможно переопределение стандартных реализаций подкоманд, но это рецепт кода, который не работает, если вы не слишком осторожны в отношении следования существующему API.

0 голосов
/ 03 марта 2020

Какой стандартный способ сделать это?

Для этой цели нет встроенной команды, один из подходов заключается в использовании dict update:

% set test [dict create]
% dict update test 1 1 { dict lappend 1 flps "o1" }
flps o1
% set test
1 {flps o1}
% dict update test 1 1 { dict lappend 1 flps "o2" }
flps {o1 o2}
% set test
1 {flps {o1 o2}}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...