我在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
答案 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}