问题是我在数组中"插入"元素的顺序会在整个脚本执行过程中发生变化.
以下是该问题的快速复制:
#!/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
Run Code Online (Sandbox Code Playgroud)
输出是:
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
Run Code Online (Sandbox Code Playgroud)
注意我没有像你想象的那样使用像A,B,C这样的通用键和1,2,3等通用值.这是因为订单不会与这些通用键/值混淆.也许这可以帮助确定问题.
还要注意初始顺序(AQHI,O3,NO2,PM2.5)即使在第一次调用时也会丢失parray(现在订单是AQHI,NO2,O3,PM2.5;按字母顺序排序?).然后在调用时再次更改array get ...(反转?)
所以无论如何,问题是:我如何确保保留初始订单?
你犯了将Tcl数组等同于C语言的错误,它是一个元素列表.相反,Tcl数组是映射(从键到值),就像Java中的HashMap一样,并且不保留元素的顺序.
您可能最好使用列表(如果您只需要按顺序存储多个项目).
如果你使用的是8.5或更高版本,那么如果你实际上有一个键值到值的映射,那么dict是因为字典是保存映射的顺序.在8.5之前有一些dict向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
Run Code Online (Sandbox Code Playgroud)
8.4的手册页在这里
您可能还想在Tcl的键控列表上查看此页面.它实现了我上面提到的,以及一些其他有用的命令.
有关有序"map"和无序"map"之间不同的示例,您可以查看两个java类HashMap(无序)和LinkedHashMap(有序).