订购两个具有相同索引的列表
order two list with the same indices
我是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
的排序对两个列表进行排序。
谁能帮帮我?
这正是 lsort
具有 -indices
选项的任务类型(需要 8.5 或更高版本)。它不是排序值列表,而是 returns 原始列表中的索引列表,按照您检索它们以获得排序列表的顺序,这非常适合您的任务。这个交互式会话(在 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]
}
使用比 8.4 更旧的 Tcl 版本需要您使用 -command
选项,这真的很慢。
我是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
的排序对两个列表进行排序。
谁能帮帮我?
这正是 lsort
具有 -indices
选项的任务类型(需要 8.5 或更高版本)。它不是排序值列表,而是 returns 原始列表中的索引列表,按照您检索它们以获得排序列表的顺序,这非常适合您的任务。这个交互式会话(在 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]
}
使用比 8.4 更旧的 Tcl 版本需要您使用 -command
选项,这真的很慢。