Tcl 如何在没有变更单的情况下获得阵列输出?

Tcl 如何在没有变更单的情况下获得阵列输出?,tcl,Tcl,我得到一个数组: array set arrayA {1 a 3 b 2 x 4 g} 如何在不更改顺序的情况下获得输出 foreach {key value} [array get arrayA] { puts $key puts $value } 如何得到下面的输出,谢谢 1 a 3 b 2 x 4 g Tcl数组不保留其元素的插入顺序(但DICT保留)。要按顺序列出元素,您需要提供所需的顺序,例如通过排序: set my_order [lsort -integer [

我得到一个数组:

array set arrayA {1 a 3 b 2 x 4 g}
如何在不更改顺序的情况下获得输出

foreach {key value} [array get arrayA] {
    puts $key
    puts $value
}
如何得到下面的输出,谢谢

1
a
3
b
2
x
4
g

Tcl数组不保留其元素的插入顺序(但DICT保留)。要按顺序列出元素,您需要提供所需的顺序,例如通过排序:

set my_order [lsort -integer [array names arrayA]]
foreach key $my_order {
    puts $key
    puts $arrayA($key)
}
但那不是你想要的

您可以通过在创建时存储名称(并在添加新名称时更新名称列表),以快速而肮脏的方式保留数组的插入顺序:

不那么快速、肮脏、更复杂、更健壮的方法是使用跟踪

这里有一种使用跟踪保持数组插入顺序的方法。跟踪可以设置为激发(运行处理程序)数组操作(调用数组上的
array
命令)、读取操作(例如
put$arrayA(1)
),我们不必担心这些、写入操作(例如
array set arrayA{1 z}
set arrayA(1)z
)和取消设置操作(例如
unset arrayA(1)
)。对我们来说,最有趣的操作是写入操作(可能会向数组中添加新元素)和取消设置操作(可能会将新元素取出)

每个操作可以有一个处理程序,或者所有操作都有一个大处理程序;我将选择后者

proc arrayOrder {varName name1 name2 op} {
    # make 'var' a link to the global variable named in the first argument
    upvar #0 $varName var
    # the three following arguments will be supplied when the trace fires:
    # 'name2' is the element name, and 'op' is the operation (array, write, or
    # unset)
    #
    # not doing anything particular with $op eq "array": you might want to
    # experiment with it to see if you have use for it
    if {$op eq "write"} {
        # is the name already in the order list?
        if {$name2 ni $var} {
            # no, it isn't, meaning it's a new element that should be added to
            # the order list
            lappend var $name2
        }
    }
    if {$op eq "unset"} {
        if {$name2 eq {}} {
            # the whole array was unset: empty the order list
            set var {}
        } else {
            # just one element was unset: remove the name from the order list
            set idx [lsearch -exact $var $name2]
            set var [lreplace $var $idx $idx]
        }
    }
}
我希望这能解决最基本的问题。现在要设置跟踪本身。请注意,跟踪是为一个变量设置的,在本例中是为三个不同的操作设置的。如果与这些操作中的一个或多个匹配的变量发生了什么事,则将为每个操作调用一次处理程序。我们使用固定的第一个参数l保存插入顺序的变量的处理程序

trace add variable arrayA {array write unset} {arrayOrder arrayA_order}
现在我们可以创建数组并在其中添加或删除成员,然后按如下插入顺序打印元素:

foreach key $arrayA_order {
    puts $key
    puts $arrayA($key)
}
请注意,如果您取消设置整个阵列,跟踪将消失,您需要恢复它

文件: , , , , , , , , , , , , , ,

正如彼得所说,字典保持秩序:

set d [dict create {*}{1 a 3 b 2 x 4 g}]
dict for {key value} $d {puts $key; puts $value}

非常感谢你给出如此清晰和详尽的答案,我学到了比我需要的更多的东西,谢谢!
set d [dict create {*}{1 a 3 b 2 x 4 g}]
dict for {key value} $d {puts $key; puts $value}