基于值的 Tcl 数组排序
Tcl array sorting based on values
我有一个数组,其中包含动态 'keys' 和与之关联的值。
我想根据值对数组进行排序,并希望能够从排序后的数组中检索 'keys'。
例如,假设我有,
for {set i 0} {$i < [db_get_nrows $rs]} {incr i} {
set x [db_get_col $rs $i abc]
set ARRAY_A($x) [db_get_col $rs $i def]
}
所以,我的数组看起来像,
ARRAY_A(111) 10
ARRAY_A(222) 50
ARRAY_A(333) 20
现在,我想根据它的值对这个数组进行排序(首先是 50,然后是 20,然后是 10)。然后我对它的键(222、333 和 111)感兴趣,以便进一步处理。
我在 Internet 上找不到太多关于此类具有动态生成键的数组的信息。
非常感谢任何帮助。
谢谢。
好吧,我只想首先提一下,您不能对数组进行排序,因为它们实际上并没有固定的顺序,但是它们的保存方式使得 easier/faster 解释器可以检索值。
如果你想按照值的顺序获取数组的键,你可以使用类似的东西:
set key_value [lmap {key val} [array get ARRAY_A] {list $key $val}]
set key_value [lsort -index 1 -integer -decreasing $key_value]
列表 key_value
现在包含按值降序排列的 key/value 对数组。 -index 1
表示排序是按子列表的第二个元素排序(Tcl 有从 0 开始的列表)。 -integer
只是指示我们正在对整数进行排序(而不是使用字典排序)。您只需要从列表中获取密钥:
foreach n $key_value {
puts [lindex $n 0]
}
如果你愿意,你可以将上面的内容组合在一个循环中(我将循环和第二行组合在一起,添加第一行会使它看起来有点太多):
foreach n [lsort -index 1 -integer -decreasing $key_value] {
puts [lindex $n 0]
}
% set tcl_version
8.6
% array set n {111 10 222 50 333 20}
% parray n
n(111) = 10
n(222) = 50
n(333) = 20
% set l [array get n]
333 20 222 50 111 10
% lsort -stride 2 -integer -index 1 $l
111 10 333 20 222 50
% lsort -stride 2 -integer -decreasing -index 1 $l
222 50 333 20 111 10
%
您可以将它们作为具有预期顺序的列表获取,然后尝试进一步应用您的逻辑。
这部分答案主要是 Dinesh 答案的补充,本身并不完整。
创建包含按值排序的数组元素的列表后,可以将其放入字典(这是另一种关联列表结构):
set d [lsort -stride 2 -integer -decreasing -index 1 $l]
字典将保留插入顺序并允许轻松访问,例如钥匙:
dict keys $d
# -> 222 333 111
eta[=33=]
如果你不能使用lmap
或-stride
,你仍然可以像这样生成一个字典:
set pairs {}
foreach {a b} [array get ARRAY_A] {
lappend pairs [list $a $b]
}
set DICT_A [concat {*}[lsort -index 1 -integer -decreasing $pairs]]
此方法将元素打包到 "pairs" 中,对打包列表进行排序,然后将其解包到一个平面列表中,以用作上面的字典。
我有一个数组,其中包含动态 'keys' 和与之关联的值。 我想根据值对数组进行排序,并希望能够从排序后的数组中检索 'keys'。 例如,假设我有,
for {set i 0} {$i < [db_get_nrows $rs]} {incr i} {
set x [db_get_col $rs $i abc]
set ARRAY_A($x) [db_get_col $rs $i def]
}
所以,我的数组看起来像,
ARRAY_A(111) 10
ARRAY_A(222) 50
ARRAY_A(333) 20
现在,我想根据它的值对这个数组进行排序(首先是 50,然后是 20,然后是 10)。然后我对它的键(222、333 和 111)感兴趣,以便进一步处理。
我在 Internet 上找不到太多关于此类具有动态生成键的数组的信息。 非常感谢任何帮助。
谢谢。
好吧,我只想首先提一下,您不能对数组进行排序,因为它们实际上并没有固定的顺序,但是它们的保存方式使得 easier/faster 解释器可以检索值。
如果你想按照值的顺序获取数组的键,你可以使用类似的东西:
set key_value [lmap {key val} [array get ARRAY_A] {list $key $val}]
set key_value [lsort -index 1 -integer -decreasing $key_value]
列表 key_value
现在包含按值降序排列的 key/value 对数组。 -index 1
表示排序是按子列表的第二个元素排序(Tcl 有从 0 开始的列表)。 -integer
只是指示我们正在对整数进行排序(而不是使用字典排序)。您只需要从列表中获取密钥:
foreach n $key_value {
puts [lindex $n 0]
}
如果你愿意,你可以将上面的内容组合在一个循环中(我将循环和第二行组合在一起,添加第一行会使它看起来有点太多):
foreach n [lsort -index 1 -integer -decreasing $key_value] {
puts [lindex $n 0]
}
% set tcl_version
8.6
% array set n {111 10 222 50 333 20}
% parray n
n(111) = 10
n(222) = 50
n(333) = 20
% set l [array get n]
333 20 222 50 111 10
% lsort -stride 2 -integer -index 1 $l
111 10 333 20 222 50
% lsort -stride 2 -integer -decreasing -index 1 $l
222 50 333 20 111 10
%
您可以将它们作为具有预期顺序的列表获取,然后尝试进一步应用您的逻辑。
这部分答案主要是 Dinesh 答案的补充,本身并不完整。
创建包含按值排序的数组元素的列表后,可以将其放入字典(这是另一种关联列表结构):
set d [lsort -stride 2 -integer -decreasing -index 1 $l]
字典将保留插入顺序并允许轻松访问,例如钥匙:
dict keys $d
# -> 222 333 111
eta[=33=]
如果你不能使用lmap
或-stride
,你仍然可以像这样生成一个字典:
set pairs {}
foreach {a b} [array get ARRAY_A] {
lappend pairs [list $a $b]
}
set DICT_A [concat {*}[lsort -index 1 -integer -decreasing $pairs]]
此方法将元素打包到 "pairs" 中,对打包列表进行排序,然后将其解包到一个平面列表中,以用作上面的字典。