首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何确保TCL不会打乱数组元素的顺序?

如何确保TCL不会打乱数组元素的顺序?
EN

Stack Overflow用户
提问于 2011-06-02 07:04:13
回答 2查看 1.8K关注 0票数 3

问题是,我在数组中“插入”元素的顺序在整个脚本执行过程中都会发生变化。

以下是问题的快速再现:

代码语言:javascript
复制
#!/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

输出为:

代码语言:javascript
复制
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 ...时再次更改它(inversed?)

所以不管怎样,问题是:我如何确保保持最初的顺序?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-06-02 18:31:32

Tcl足够灵活,可以设计出许多方案来处理您想要的内容。假设空字符串不是数据中的有效键,这里有一个想法,即在数组中存储键的顺序:

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2011-06-02 07:10:20

将Tcl数组等同于C语言中的Tcl数组是错误的,在C语言中,Tcl数组是一个元素列表。相反,Tcl数组是映射(从键到值),就像Java语言中的HashMap一样,元素的顺序不会被保留。

使用列表可能会更好(如果您只需要按顺序存储多个项目)。

如果你使用的是8.5或更高版本,如果你实际上有一个键到值的映射,那么就需要一个dict,因为字典是保持顺序的映射。对于8.5之前的Tcl版本,有一些dict backport,但我不确定它们是否保持了秩序(而且速度更慢)。

如果不能使用8.5字典并且需要键/值对,一种选择是使用键值对列表,然后使用lsearch提取所需的值

代码语言:javascript
复制
> 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

你可能还想看看Tcl在keyed lists上的这个页面。它实现了我上面提到的内容,外加一些其他有用的命令。

有关有序“映射”和无序“映射”之间的区别的示例,您可以查看两个java类HashMap (无序)和LinkedHashMap (有序)。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6208727

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档