计算重复列表的频率 - 在列表列表

时间:2016-02-10 13:08:34

标签: python list python-2.7 counter

我在python中有一个列表列表,我需要查找每个子列表发生了多少次。这是一个样本,

from collections import Counter
list1 = [[ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333], 
         [ 1., 2., 2.], [ 1., 2.66666667, 1.33333333], [ 1., 4., 2.5],
         [ 1., 2.66666667, 1.33333333]]   
c = Counter(x for x in iter(list1))
print c

我上面的代码可以工作,如果列表的元素是可以删除的(比如int),但在这种情况下它们是列表而且我收到错误

TypeError: unhashable type: 'list'

我如何计算这些列表,以便得到类似

的内容
[ 1., 2.66666667, 1.33333333], 3
[ 1., 4., 2.5], 2
[ 1., 2., 2.], 1

3 个答案:

答案 0 :(得分:10)

只需将列表转换为tuple

即可
>>> c = Counter(tuple(x) for x in iter(list1))
>>> c
Counter({(1.0, 2.66666667, 1.33333333): 3, (1.0, 4.0, 2.5): 2, (1.0, 2.0, 2.0): 1})

请记住为查找做同样的事情:

>>> c[tuple(list1[0])]
2

答案 1 :(得分:2)

计数器返回一个类似于对象的字典,它的键必须是可以清除的。由于列表不可清除,您可以使用tuple函数将其转换为map

>>> Counter(map(tuple, list1))
Counter({(1.0, 2.66666667, 1.33333333): 3, (1.0, 4.0, 2.5): 2, (1.0, 2.0, 2.0): 1})

请注意,使用map的性能稍好于生成器表达式,因为通过将生成器表达式传递给Counter(),python将自动从生成器函数中获取值,因为使用内置函数{{ 1}}在执行时间 1 方面具有更高的性能。

map

来自PEP 0289 -- Generator Expressions

  

生成器表达式的语义等同于创建匿名生成器函数并调用它。例如:

# Use generator expression
~ $ python -m timeit --setup "list1 = [[ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333],[ 1., 2., 2.], [ 1., 2.66666667, 1.33333333], [ 1., 4., 2.5],[ 1., 2.66666667, 1.33333333]] ;from collections import Counter" "Counter(tuple(x) for x in iter(list1))"
100000 loops, best of 3: 9.86 usec per loop
# Use map
~ $ python -m timeit --setup "list1 = [[ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333],[ 1., 2., 2.], [ 1., 2.66666667, 1.33333333], [ 1., 4., 2.5],[ 1., 2.66666667, 1.33333333]] ;from collections import Counter" "Counter(map(tuple, list1))"
100000 loops, best of 3: 7.92 usec per loop
     

相当于:

g = (x**2 for x in range(10))
print g.next()

<子> 请注意,由于生成器表达式在内存使用方面更好,如果您处理大数据,最好使用生成器表达式而不是 map 功能。

答案 2 :(得分:1)

试试这个

list1 = [[ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333], 
         [ 1., 2., 2.], [ 1., 2.66666667, 1.33333333], [ 1., 4., 2.5],
         [ 1., 2.66666667, 1.33333333]]

counter = {}
for el in list1:
    el = str(el)     #This sorts your hashable part or use tuple(el)
    if el in counter:
        counter[el]+=1
    else:
        counter[el]=1

print(counter)

应输出

{'[1.0, 2.0, 2.0]': 1, '[1.0, 2.66666667, 1.33333333]': 3, '[1.0, 4.0, 2.5]': 2}