Как отсортировать словарь в tcl с несколькими индексами

У меня есть словарь в 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}. Если 2 ключа имеют одинаковое значение для {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

Но приведенный выше код не сортирует содержимое со вторым элементом списка, если оба имеют одинаковое значение для индекса {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.

Алгоритм сортировки слиянием (с кодом на Python, Java, JavaScript, PHP, C++)
Алгоритм сортировки слиянием (с кодом на Python, Java, JavaScript, PHP, C++)
Merge sort - самый популярный алгоритм сортировки, основанный на принципе алгоритма "разделяй и властвуй".
Сортировка hashmap по значениям
Сортировка hashmap по значениям
На Leetcode я решал задачу с хэшмапой и подумал, что мне нужно отсортировать хэшмапу по значениям.
0
0
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вы пишете функцию, которая сравнивает два списка поэлементно, ее можно использовать с параметрами lsort, -stride и -index для сортировки по желанию, передавая значения dict в эту функцию сравнения.

#!/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"
}

выходы

4: 2 12 36
5: 7 16 9
3: 10 5 15
1: 10 20 30
2: 10 25 45

Спасибо, @Шон. Кажется, это работает нормально, но, как вы упомянули, есть ли способ заставить его работать с параметром шага и команды lsort?

Sourav Das 28.05.2023 20:18

@SouravDas Поигравшись с различными комбинациями вариантов lsort, да, я нашел способ. Смотрите пересмотренный ответ. Теперь я чувствую себя глупо из-за того, что не исследовал этот подход более оригинально.

Shawn 28.05.2023 21:15

Я не знаю, как вам благодарить, но это именно то, что я хотел.

Sourav Das 28.05.2023 21:48

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

Вы можете расширить это на любое количество ключей. Просто начните сортировку по наименее значимому ключу и продвигайтесь к наиболее значимому ключу.

@Scelte Брон. Это тоже выглядит просто и круто.

Sourav Das 29.05.2023 21:41

Другие вопросы по теме