如何从列表中生成摘要?

时间:2017-11-01 03:04:56

标签: tcl

我有一个清单:

set aList {aa aa aa bb bb cc cc cc cc aa aa bb cc cc cc cc}

我想生成一个类似于:

的摘要
3 aa 2 bb 4 cc 2 aa 1 bb 4 cc

我可以使用foreach循环生成摘要,但我正在寻找更好的解决方案。

2 个答案:

答案 0 :(得分:0)

你要求的基本上是一个RLE编码命令。我不知道,但可能有一个地方 - 它是否适合你的格式是另一回事。在维基上有一个名为RLE的页面,但这只是一个用户签名。

否则,在处理迭代结构时很难避免迭代命令。你可以试试递归:

set aList {aa aa aa bb bb cc cc cc cc aa aa bb cc cc cc cc}

proc summarize {result theList} {
    if {[llength $theList] eq 0} {
        return $result
    } else {
        summarize {*}[count $result $theList 1]
    }
}

proc count {result theList theCount} {
    set theList [lassign $theList theToken]
    if {$theToken eq [lindex $theList 0]} {
        count $result $theList [incr theCount]
    } else {
        list [lappend result $theCount $theToken] $theList
    }
}

summarize [list] $aList

简短评论:summarize函数使用两个列表,一个偶数大小(最初为空)的计数和标记列表(result)和一个未处理的标记列表(theList )。如果theList为空,则result列表是操作的结果。如果theList中至少有一个令牌,我们会通过计算theList头部中有多少相同的令牌来准备一对新的类似列表,并总结这两个列表。对于每个应用程序,result将更长一对,theList将缩短一定数量的令牌≥1。

它可以象征性地表示(使用准ML表示法)

总结(R,Ø)→R
总结(R,L)→总结计数(R,L,1)

count函数使用相同的两个列表,并且还有一个计数(最初为1:如果theList不为空,我们将始终至少有一个令牌来计算)。它在theList的头部中断了一个标记,并将其与(现在缩短的)theList进行比较。如果theTokentheList中的第一个令牌相同,我们会增加theCount并再次应用count。如果不是,我们将resulttheCounttheToken一起扩展,并计算了一种令牌(执行然后通过调用层返回summarize )。

请注意,使用count的空列表调用theList会导致无限循环:除非theList中有令牌,否则摘要永远不会调用它。

count(R,(T ::(T :: L)),N)→count(R,(T :: L),N + 1)
count(R,( a :: L),N)→((R @(N ::( a ::Ø))),L)

答案 1 :(得分:0)

以下功能贯穿列表并保持当前项目的计数:

proc group_identical {slist} {
    set newlist {}
    set current [lindex $slist 0] 
    set count 0
    foreach ele $slist {
        if { ![string compare $ele $current] } {  ;# same as current; 
            incr count
        } else {                ;# new element
            lappend newlist $count $current
            set current $ele
            set count 1
        }
    }
    lappend newlist $count $current
    return $newlist
}

set aList {aa aa aa bb bb cc cc cc cc aa aa bb cc cc cc cc}
puts [group_identical $aList]

输出:

3 aa 2 bb 4 cc 2 aa 1 bb 4 cc