The problem is that your code doesn't have enough information at the point where a number is added to numbered
. Get the information first, and then apply it.
First, create a list where each item is a list consisting of one of the unique numbers in $unnumbered
and the indices in $unnumbered
where that number occurs:
lmap n [lsort -unique $unnumbered] {
list $n [lsearch -all $unnumbered $n]
}
# => {101 {0 1 2}} {102 {3 4}} {103 5} {104 6} {105 {7 8 9}} {106 10}
For each of those items, split up the item into n
= the number and indices
= the indices. Check how many indices you have. For more than one index, add enumerated numbers like this:
set i 0
foreach index $indices {
lappend numbered $n.[incr i]
}
For single indices, just add the number:
lappend numbered $n
The whole program looks like this:
set unnumbered [list 101 101 101 102 102 103 104 105 105 105 106]
set numbered [list]
foreach item [lmap n [lsort -unique $unnumbered] {
list $n [lsearch -all $unnumbered $n]
}] {
lassign $item n indices
if {[llength $indices] > 1} {
set i 0
foreach index $indices {
lappend numbered $n.[incr i]
}
} else {
lappend numbered $n
}
}
Documentation:
> (operator),
foreach,
if,
incr,
lappend,
lassign,
list,
llength,
lmap (for Tcl 8.5),
lmap,
lsearch,
lsort,
set
If you don’t have lmap
, see the link above. If you don’t have lassign
, use
foreach {n indices} $item break
instead.
ETA If the "no index on singleton numbers" requirement can be relaxed, one could do it this way:
set previous {}
lmap num $unnumbered {
if {$num ne $previous} {
set i 0
}
set previous $num
format %d.%d $num [incr i]
}
Another variant. It’s very similar to Jerry’s second suggestion, but I didn’t see that one until I was going to submit this, honest. This one assumes that no element in $unnumbered
is the empty string.
set numbered [list]
set rest [lassign $unnumbered current next]
set i 0
while 1 {
if {$current eq $next} {
lappend numbered $current.[incr i]
} else {
if {$i > 0} {
lappend numbered $current.[incr i]
set i 0
} else {
lappend numbered $current
}
set current $next
}
if {$next eq {}} break
set rest [lassign $rest next]
}