заказать два списка с одинаковыми индексами - PullRequest
0 голосов
/ 26 октября 2018

Я новичок в Tcl. Мне нужно отсортировать список значений и сохранить индексы. У меня есть 2 списка, и я хочу отсортировать listA, но затем я хочу заказать listB, сохраняя индексы в форме listA.

Например:

set listA {5 6 7 3 4 7 8 9}
set listB {0 1 2 3 4 5 6 7}

set sort_listA [lsort $listA]

Теперь sort_listA будет 3 4 5 6 7 7 8 9.

Я хочу отсортировать список listB, сохранив те же индексы sort_listA, как:

3 4 0 1 2 5 6 7

Другими словами, мне нужно отсортировать оба списка с сортировкой listA. Кто-нибудь может мне помочь?

1 Ответ

0 голосов
/ 26 октября 2018

Это именно та задача, для которой lsort имеет опцию -indices (требуется 8.5 или более поздняя версия).Вместо списка отсортированных значений он возвращает список индексов в исходный список в том порядке, в котором вы их получите, чтобы получить отсортированный список, и это идеально подходит для вашей задачи.Этот интерактивный сеанс (в Tcl 8.6, поэтому у меня есть lmap) является ориентировочным:

% set listA {5 6 7 3 4 7 8 9}
5 6 7 3 4 7 8 9
% set listB {0 1 2 3 4 5 6 7}
0 1 2 3 4 5 6 7
% set idxs [lsort -indices $listA]
3 4 0 1 2 5 6 7
% lmap i $idxs {lindex $listA $i}
3 4 5 6 7 7 8 9
% lmap i $idxs {lindex $listB $i}
3 4 0 1 2 5 6 7

Если вы все еще на 8.5, вы можете использовать foreach для переназначения;проще с процедурой:

proc mapindices {indexlist valuelist} {
    set result {}
    foreach i $indexlist {
        lappend result [lindex $valuelist $i]
    }
    return $result
}
set listA {5 6 7 3 4 7 8 9}
set listB {0 1 2 3 4 5 6 7}
puts [mapindices [lsort -indices $listA] $listB]

Теперь, в 8.4 (больше не поддерживается!) нет опции индексов, поэтому вам нужно проделать дополнительную работу.

proc lsortIndices {list} {
    # Pair each value up with its index
    set zipped {}
    set idx -1
    foreach val $list {
        lappend zipped [list [incr idx] $val]
    }

    # Do the sorting by the value of the pair
    set sorted [lsort -index 1 $zipped]

    # Unpack the indices from the pairs to get the result
    set result {}
    foreach pair $sorted {
        lappend result [lindex $pair 0]
    }
    return $result
}

Однако на этомукажем, что вы, вероятно, просто объедините два списка вместе и будете работать более напрямую:

set zipped {}
foreach valA $listA valB $listB {
    lappend zipped [list $valA $valB]
}

set sorted [lsort -index 0 $zipped]

set listAsorted {}
set listBsorted {}
foreach pair $sorted {
    lappend listAsorted [lindex $pair 0]
    lappend listBsorted [lindex $pair 1]
}

Работа с более старыми версиями Tcl, чем 8.4, потребует от вас использования опции -command, и это очень медленно.

...