2015-06-30 155 views
1

我的詞典列表:變換的詞典列表,以列表的詞典內置字典命令

set personA {name Alice age 35} 
set personB {name Bob age 42} 
set persons [list $personA $personB] 

現在我想給他們「轉」到包含列表,而不是單一的詞典:

set transposedPersons {name {Alice Bob} age {35 42}} 

我可以使用下面的代碼實現這一點:

set keys {name {} age {}} 
set transposedPersons [dict map {k _} $keys { 
    lmap person $persons {dict get $person $k} 
}] 

我不FUL請理解一些內置的dict命令的作用,例如dict mergedict updatedict with。我想知道是否可以使用其中之一來簡化字典列表的換位。

特別是:我可以以某種方式自動使用原始字典中的鍵nameage,而不必再次寫出它們嗎?

(我僅限於Tcl的8.5,但仍然有興趣在需要的Tcl 8.6的解決方案。)

回答

2
foreach person $persons { 
    dict for {key val} $person { 
     dict lappend transposedPersons $key $val 
    } 
} 

你想要做的是每個鍵下逐步增加值命名字典transposedPersons。您需要的操作是dict lappend transposedPersons $key $val

鍵和值取自描述人的字典。要迭代存儲在變量person中的一個字典中的鍵和對應值,可以使用dict for {key val} $person { ... }

字典是列表中的元素。要遍歷人字典,請使用foreach person $persons { ... }

dict merge命令將大量字典值作爲參數,並創建一個包含所有這些字典中所有鍵的組合字典值。每個鍵的值是最後一個字典中具有該鍵的值。所以

dict merge {a 1 d 9} {b 2 d 8} {c 3 d 7} 
# -> a 1 d 7 b 2 c 3 

產生的字典會從三個不同的詞典共四個鍵,用公用密鑰d從上次字典獲取值7。但請注意,密鑰d插入在ab之間,因爲密鑰的第一次出現是在a之後但在b之前。

dict update命令採用字典變量,一組鍵變量名稱映射和腳本。在評估腳本之前,會創建一組局部變量,分配新值或取消設置,具體取決於給定的字典變量中存在哪些鍵。如果映射中指定的變量已經存在,那麼如果鍵存在,則其值將被與該鍵相關聯的值覆蓋:如果不存在,則該變量未設置。如果一個變量不存在,如果相應的鍵存在,它將被創建。

評估腳本後,每個這些變量(如果存在)都將其值插入到相應鍵下的字典中。如果該變量未設置,則該鍵被刪除。

如果假定

set d {firstname Sally lastname Bowles balance 2000 address {Foo Street}} 
set amt 150 
set script { 
    if {![info exists mn]} {set mn H} 
    unset addr 
    if {$amt > 0} {set bal [expr {$bal-$amt}]} 
} 

以下調用

dict update d firstname fn middlename mn lastname ln balance bal address addr $script 

大致相當於

set mappings {firstname fn middlename mn lastname ln balance bal address addr} 
foreach {keyname varname} $mappings { 
    if {[dict exists $d $keyname]} { 
     set $varname [dict get $d $keyname] 
    } else { 
     unset -nocomplain $varname 
    } 
} 
eval $script 
foreach {keyname varname} $mappings { 
    if {[info exists $varname]} { 
     dict set d $keyname [set $varname] 
    } else { 
     dict unset d $keyname 
    } 
} 

除了輔助變量(keyname等)沒有建立。

在這兩種情況下,在d更新字典包含

firstname Sally lastname Bowles balance 1850 middlename H 

即新創建密鑰,另一個被刪除,第三有它的價值改變了,因爲發生了什麼事在腳本中的變量。

在評估完命令後,映射變量繼續存在於本地作用域中。

dict with命令類似,但將字典中的所有鍵映射爲與鍵名稱相同的變量,並且該命令還允許指定鍵鏈以獲取字典的子字典。我舉一個例子,但這個答案已經太長了。

文檔:dictevalexprforeachifinfosetunset

1

因爲以維持通過每個參考一個不變的觀點TCL將自動根據需要複製幕後值,可以實際做到這一點:

# I prefer to use 「-」 as my ignored variable name, and not 「_」. YMMV 
set transposedPersons [dict map {k -} [lindex $persons 0] { 
    lmap person $persons {dict get $person $k} 
}] 

,它假定在$persons每個字典具有相同的一組鍵作爲第一個,但對於跨必要無論如何你都可以按照你的工作方式工作。 (Tcl確實是而不是有一個NULL;它對應於一個未設置的變量或一個缺席的關鍵字。)