英文:
How to sort a dictionary in tcl with multiple index
问题
我有一个在Tcl中的字典,其中值是一个项目列表。例如,考虑下面给出的字典:
1: {10,20,30}
2: {10,25,45}
3: {10,5,15}
4: {2,12,36}
5: {7,16,9}
其中1,2,3,4,5是键,而值用花括号表示。我想根据列表值的第一个项目,{index 1 0},对字典进行排序。如果两个键具有相同的{index 1 0}值,我应该根据列表值的第二个项目,{index 1 1},进行排序。最后,我应该按排序顺序返回键。目前,我正在使用lsort来对内容进行排序。但是如果两个键具有相同的{index 1 0}值,我无法排序。我正在使用Tcl 8.6版本。目前,我正在使用以下代码:
set sorted [lsort -stride 2 -integer -index {1 0} $dict_name]
set get_keys [dict keys $sorted]
puts $get_keys
但是上述代码无法对具有相同{index 1 0}值的第二个项目进行排序。
期望的输出:
4: {2,12,36}
5: {7,16,9}
3: {10,5,15}
1: {10,20,30}
2: {10,25,45}
键4具有索引0的最低值,然后是键5。由于键1、2和3的索引0的值相同,它们根据索引1的值进行排序。
英文:
I have a dictionary in tcl where the value is a list of items. For example, consider the dictionary given below:
1: {10,20,30}
2: {10,25,45}
3: {10,5,15}
4: {2,12,36}
5: {7,16,9}
where 1,2,3,4,5 are the keys, and the values are represented in braces. I want to sort the dictionary based on the first item of the list value, {index 1 0}. If 2 keys have the same value for {index 1 0}, I should sort by the second item of the list value, {index 1 1}. Finally, I should return the keys in the sorted order. Currently, I am using lsort to sort the contents. But I am not able to sort if two keys have the same { index 1 0 } value. I am using tcl 8.6. Currently, I am using the following code:
set sorted [lsort -stride 2 -integer -index {1 0} $dict_name]
set get_keys [dict keys $sorted ]
puts $get_keys
But the above code does not sort contents with the second item of the list if both have the same value for index {1 0}.
Expected output:
4: {2,12,36}
5: {7,16,9}
3: {10,5,15}
1: {10,20,30}
2: {10,25,45}
Key 4 has the lowest value for index 0, followed by key 5. Since keys 1,2, and 3 have the same value for index 0, they are sorted based on the values of index 1.
答案1
得分: 2
如果你编写一个比较两个列表逐元素的函数,它可以与lsort
的-stride
、-index
和-command
选项一起使用,通过将字典的值传递给该比较函数来按所需方式排序。
#!/usr/bin/env tclsh
# 逐元素比较两个整数列表的值
proc sortIntLists {a b} {
set lenA [llength $a]
set lenB [llength $b]
set len [::tcl::mathfunc::min $lenA $lenB]
for {set n 0} {$n < $len} {incr n} {
set diff [expr {[lindex $a $n] - [lindex $b $n]}]
if {$diff != 0} {
return $diff
}
}
# 所有已比较的列表元素对都相等
# 如果列表长度不同,较短的列表较小
if {$lenA == $lenB} {
return 0
} elseif {$lenA < $lenB} {
return -1
} else {
return 1
}
}
set myDict {
1 {10 20 30}
2 {10 25 45}
3 {10 5 15}
4 {2 12 36}
5 {7 16 9}
}
set mySortedDict [lsort -stride 2 -index 1 -command sortIntLists $myDict]
dict for {k v} $mySortedDict {
puts "$k: $v"
}
输出结果:
4: 2 12 36
5: 7 16 9
3: 10 5 15
1: 10 20 30
2: 10 25 45
英文:
If you write a function that compares two lists element-by-element, it can be used with lsort
's -stride
, -index
and -command
options to sort as desired by passing the values of the dict to that comparison function.
#!/usr/bin/env tclsh
# Compare two values of integer lists element by element
proc sortIntLists {a b} {
set lenA [llength $a]
set lenB [llength $b]
set len [::tcl::mathfunc::min $lenA $lenB]
for {set n 0} {$n < $len} {incr n} {
set diff [expr {[lindex $a $n] - [lindex $b $n]}]
if {$diff != 0} {
return $diff
}
}
# Every pair of elements of the lists looked at has been equal
# now if the lists are different lengths the shorter one is smaller
if {$lenA == $lenB} {
return 0
} elseif {$lenA < $lenB} {
return -1
} else {
return 1
}
}
set myDict {
1 {10 20 30}
2 {10 25 45}
3 {10 5 15}
4 {2 12 36}
5 {7 16 9}
}
set mySortedDict [lsort -stride 2 -index 1 -command sortIntLists $myDict]
dict for {k v} $mySortedDict {
puts "$k: $v"
}
outputs
4: 2 12 36
5: 7 16 9
3: 10 5 15
1: 10 20 30
2: 10 25 45
答案2
得分: 1
Tcl使用稳定的排序算法。要使用次要键解决主键上的重复项,请首先按次要键排序,然后按主键排序结果:
set data {
1 {10 20 30}
2 {10 25 45}
3 {10 5 15}
4 {2 12 36}
5 {7 16 9}
}
set temp [lsort -stride 2 -integer -index {1 1} $data]
set final [lsort -stride 2 -integer -index {1 0} $temp]
puts [dict keys $final]
结果:4 5 3 1 2
您可以将此方法扩展到任意数量的键。只需从最不重要的键开始排序,然后逐渐到最重要的键。
英文:
Tcl uses a stable sort algorithm. To resolve duplicates on the primary key by using a secondary key, sort by the secondary key first, then sort the result by the primary key:
set data {
1 {10 20 30}
2 {10 25 45}
3 {10 5 15}
4 {2 12 36}
5 {7 16 9}
}
set temp [lsort -stride 2 -integer -index {1 1} $data]
set final [lsort -stride 2 -integer -index {1 0} $temp]
puts [dict keys $final]
Result: 4 5 3 1 2
You can extend this to as many keys as you want. Just start sorting by the least significant key and work your way to the most significant key.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论