计算列表中唯一元素的数量

Count number of unique element in a list

假设我有一个列表,a b c b b d e e f …,我不知道里面有多少种不同的元素。

如何计算每个唯一元素的数量并打印出来? 输出看起来像:

a: 32
b: 12
c: 6
…

你得数一数。这对于计数器数组或字典来说并不难。我将使用字典,因为它们将按首次出现的顺序打印。 (对于数组,您会得到一个“随机”顺序,或者您必须对它们进行排序。)

set counters {}
foreach item $list {
    dict incr counters $item
}
dict for {item count} $counters {
    puts "${item}: $count"
}

如果您有 8.4 或更旧版本的 TCL,请尝试此操作,

set lst "a a a a b b b c c c d d a a a f f f f f s s s s"

set unique [lsort -unique $lst]    
foreach f $unique {
    set cnt 0
    foreach item $lst {
        if {$item == $f} {
            incr cnt
        }
    }
    puts "$f :: $cnt"
}

给出类似的输出,

% tclsh main.tcl
a :: 7
b :: 3                                                                                                                                                              
c :: 3
d :: 2                                                                                                                                                              
f :: 5
s :: 4

dictarray 解决方案是最好的解决方案,应该首选。另一种适用于已排序标记列表的方法是匹配非空白标记的连续区域。

% regexp -all -inline {(\S+)(?:\s+)*} {a a b b b c d d}
{a a} a {b b b} b c c {d d} d

结果是一个均匀大小的列表,其中包含交替匹配的令牌区域和该区域中匹配的令牌。这可用于打印 list.

列表中标记的频率报告
foreach {a b} [regexp -all -inline {(\S+)(?:\s+)*} [lsort $list]] {
    puts "$b: [llength $a]"
}

注意标记不能包含空格的限制。这可以克服,但使用数组/字典解决方案更简单,它只需要标记是有效的列表元素。

文档:foreach, llength, lsort, puts, Syntax of Tcl regular expressions, regexp

使用 lsearch 和 llength 可以轻松完成。
假设您的列表是 {a c a c s a a c a} 那么,

set tempList {a c a c s a a c a}  
puts "c : [llength [lsearch -all $tempList  c]]"  
puts "a : [llength [lsearch -all $tempList  a]]"  
puts "d : [llength [lsearch -all $tempList  d]]"  

输出:
c : 3
一:5
d : 0

解释:lsearch -all,将return所有匹配元素的索引 并且这个索引列表被return编辑为llength,它将计算列表的长度。