问题在于,在整个脚本执行过程中,我在数组中“插入”元素的顺序会发生变化。
以下是问题的快速复制:
#!/bin/bash
# : \
exec /home/binops/afse/eer/eer_SPI-7.3.1/tclsh "$0" "$@"
proc myProc { theArray } {
upvar $theArray theArrayInside
parray theArrayInside
puts "------"
foreach { key value } [array get theArrayInside] {
puts "$key => $value"
}
}
# MAIN
set myArray(AQHI) AQHI
set myArray(O3) 1
set myArray(NO2) 2
set myArray(PM2.5) 3
parray myArray
puts "------"
myProc myArray
输出是:
myArray(AQHI) = AQHI
myArray(NO2) = 2
myArray(O3) = 1
myArray(PM2.5) = 3
------
theArrayInside(AQHI) = AQHI
theArrayInside(NO2) = 2
theArrayInside(O3) = 1
theArrayInside(PM2.5) = 3
------
PM2.5 => 3
O3 => 1
NO2 => 2
AQHI => AQHI
注意我没有像你想象的那样使用像A,B,C这样的通用键和1,2,3等通用值。这是因为订单不会与这些通用键/值混淆。也许这可以帮助确定问题。
另请注意,即使在第一次调用parray
时,初始订单(AQHI,O3,NO2,PM2.5)也会丢失(订单现在是AQHI,NO2,O3,PM2.5;按字母顺序排序? )。然后在调用array get ...
(反转?)
所以无论如何,问题是:我如何确保保留初始订单?
答案 0 :(得分:6)
你犯了将Tcl数组等同于C语言的错误,它是一个元素列表。相反,Tcl数组是映射(从键到值),如Java中的HashMap,并且不保留元素的顺序。
您可能最好使用列表(如果您只需要按顺序存储多个项目)。
如果您使用的是8.5或更高版本,则dict如果您实际拥有键值到映射的映射,则字典是订单保留映射。在8.5之前有一些dcl向Tcl版本的移植,但我不确定它们是否保留顺序(并且它们更慢)。
如果你不能使用8.5 dicts并且需要键/值对,一个选项是使用键值对列表然后使用lsearch来提取你需要的值
> set mylist {{key1 value1} {key2 value2} {key3 value3}}
> lsearch -index 0 $mylist key2
0
> lindex $mylist [list [lsearch -index 0 $mylist key2] 1]
> value2
> proc kv_lookup {dictList key} {
set index [lsearch -index 0 $dictList $key]
if {$index < 0} {
error "Key '$key' not found in list $dictList"
}
return [lindex $dictList [list $index 1]]
}
> kv_lookup $mylist key2
value2
8.4的手册页为here
您可能还想在keyed lists上查看此页面以获取Tcl。它实现了我上面提到的,以及一些其他有用的命令。
有关有序“地图”和无序“地图”之间不同的示例,您可以查看两个java类HashMap(无序)和LinkedHashMap(有序)。
答案 1 :(得分:0)
Tcl足够灵活,可以设计出许多方案来处理你想要的东西。假设空字符串不是数据中的有效密钥,这是一个存储密钥在数组本身中的顺序的想法:
proc array_add {ary_name key value} {
upvar 1 $ary_name ary
set ary($key) $value
lappend ary() $key
}
proc array_foreach {var_name ary_name script} {
upvar 1 $var_name var
upvar 1 $ary_name ary
foreach var $ary() {
uplevel 1 $script
}
}
array_add a foo bar
array_add a baz qux
array_add a abc def
array_add a ghi jkl
array_foreach key a {puts "$key -> $a($key)"}
# foo -> bar
# baz -> qux
# abc -> def
# ghi -> jkl
array names a
# ghi {} foo baz abc
array get a
# ghi jkl {} {foo baz abc ghi} foo bar baz qux abc def
parray a
# a() = foo baz abc ghi
# a(abc) = def
# a(baz) = qux
# a(foo) = bar
# a(ghi) = jkl