为TCL列表添加后缀

时间:2016-10-24 15:56:08

标签: algorithm list tcl

我有一个包含列表的列表。

{
    {1, A},
    {2, A},
    {4, A},
    {6, B},
    {2, B},
    {7, C}
}

如何重复搜索第二个元素并添加索引?

预期产出:

{
    {1, A<0>},
    {2, A<1>},
    {4, A<2>},
    {6, B<0>},
    {2, B<1>},
    {7, C}
}

2 个答案:

答案 0 :(得分:1)

Tcl列表通常没有除元素之外的空格之外的分隔符,并且如果有一个子列表由大括号内的项表示,则在子列表后明确禁止使用逗号。

set list {
    {1 A}
    {2 A}
    {4 A}
    {6 B}
    {2 B}
    {7 C}
}

set res {}
foreach item $list {
    set letter [lindex $item 1]
    if {[info exists num($letter)]} {
        incr num($letter)
    } else {
        set num($letter) 0
    }
    lset item 1 $letter<$num($letter)>
    lappend res $item
}

该算法包括遍历列表列表foreach并查看子列表中第二个元素(索引#1)的字母。数组num用于计算每个字母发生的次数。如果num($letter)存在,我们之前已经计算了这封信,并且只是增加了计数。如果没有,则为新字母,我们将计数设置为0.我们将该字母与包含该计数的后缀一起写回(使用lset),最后将更改的子列表添加到列表{{ 1}}。

如果你有res,你可以稍微简化一下代码:

lmap

文档: foreachifincrinfolappendlindexlmap (for Tcl 8.5)lmaplsetset

答案 1 :(得分:1)

使用Tcl 8.6

proc update {list} {
    lmap elem $list {
        set val [lindex $elem end]
        set n [expr {[incr count($val)] - 1}]
        lset elem end "$val<$n>"
    }
}

set a {{1 A} {2 A} {4 A} {6 B} {2 B} {7 C}}
set new [update $a]