如何在Tcl中使用多个索引对字典进行排序

huangapple go评论69阅读模式
英文:

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 &lt; $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 &lt; $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 &quot;$k: $v&quot;
}

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.

huangapple
  • 本文由 发表于 2023年5月28日 05:33:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76349142.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定