if 0 {Richard Suchenwirth 2004-08-27 - In the Tcl chatroom, JPS discussed an extension to lsort which returns a list of indices in sorted order (TIP#217) but for now, here's a pure-Tcl implementation: }
proc lsort-indices list { if [llength $list] { set i -1 foreach e $list {lappend tmp [list [incr i] $e]} foreach e [lsort -index 1 $tmp] {lappend res [lindex $e 0]} set res } }
if 0 {Testing:
% lsort-indices {c b a} 2 1 0 % lsort-indices {} % lsort-indices {a a a} 0 1 2
RS removed the initialisations of tmp and res, but then had to guard the body with a one-armed if - it implies "else {}", which is the correct return value for an empty list.
Lars H had this solution, which is said to be up to a third faster:
proc lsort-indices itemL { set pairL [list] foreach item $itemL { lappend pairL [list $item [llength $pairL]] } set indexL [list] foreach pair [lsort -index 0 $pairL] { lappend indexL [lindex $pair 1] } return $indexL }
wdb This version allows all switches except -index (but I did not care of speed):
proc lsort-indices args { set unsortedList [lindex $args end] set switches [lrange $args 0 end-1] set pairs {} set i -1 foreach el $unsortedList { lappend pairs [list [incr i] $el] } set result {} foreach el [eval lsort $switches [list -index 1 $pairs]] { lappend result [lindex $el 0] } set result }
Now test it:
% lsort-indices {9 10 11} 1 2 0 % lsort-indices -integer {9 10 11} 0 1 2 %
Additional list functions | Arts and crafts of Tcl-Tk programming }