如何将这个元组的元组转换为其元素的计数?
我有一个包含多个元组的元组:
TupleOfTuples = (('Venue1', 'Name1'), ('Venue1', 'Name2'),
('Venue2', 'Name3'), ('Venue3', 'Name4'),
('Venue3', 'Name5'), ('Venue3', 'Name6'))
我想把它转换成这样的结果:
Output = (('Venue1', 2), ('Venue2', 1), ('Venue3', 3))
在这个例子中,Output
包含 ('Venue1', 2)
,其中 2
是 'Venue1'
在 TupleOfTuples
中出现的次数。
我试着用 len()
来计算出现的次数,但由于 TupleOfTuples
不是一个单独的元组,而是一个元组的元组,所以这样做不行。
在 Python2.7 中,我该怎么做呢?
2 个回答
你可以很快很简单地用 zip(*TupleOfTuples)[n]
来获取所有要计数的元素序列(这里的 n
是你想要计数的每个 TupleOfTuples
元组中的元素索引;在这个例子中是 0
),然后遍历结果来统计每个独特元素的数量。
下面是具体的代码示例:
TupleOfElements = zip(*TupleOfTuples)[0]
Output = tuple((e, TupleOfElements.count(e)) for e in set(TupleOfElements))
我来解释一下这个过程:
zip(*TupleOfTuples)[0]
会把你的输入序列进行 转置。我们想要每个 TupleOfTuples
元组中的第一个元素,所以从结果中取 [0]
。我们把这个序列赋值给 TupleOfElements
。如果你想要统计 Name* 元素的话,可以用 zip(*TupleOfTuples)[1]
。
tuple((e, TupleOfElements.count(e)) for e in set(TupleOfElements))
通过遍历 TupleOfElements
来创建你想要的 Output
,为每个独特元素返回一个元素-计数对:TupleOfElements
包含了 所有 TupleOfTuples
元素的正确数量,所以我们可以用 TupleOfElements.count(uniqueElement)
来告诉我们 uniqueElement
出现了多少次。不过,我们不需要也不想对任何特定元素检查超过一次,所以我们遍历 set(TupleOfElements)
,这个集合中每个元素只会出现一次。最后,我们把结果赋值给 Output
,就完成了!
注意:这个结果会返回一个
tuple
。如果你想要一个list
,只需把第二行的tuple(..)
替换成[..]
,内容保持不变。关于性能:这段代码运行速度似乎比 Martijn 使用
collections.Counter
的非常好的解决方案快很多——在给定的例子TupleOfTuples
中快了大约 3.5 倍,而在我自己为了好奇而做的一个更大但更简单的 88,888 元素测试中快了大约 1.25 倍——我想这可能是因为它用元组和迭代器替代了字典创建的步骤。虽然它可能没有那么优雅,但我还是对此有点自豪。
使用 collections.Counter()
可以帮你计算某个东西出现了多少次:
from collections import Counter
Output = Counter(t[0] for t in TupleOfTuples).items()
Counter()
是一种字典,里面的键对应着出现的次数;你只需要传入一个生成器表达式,它就会自动帮你数了。因为它是字典的一个子类,所以你可以用 dict.items()
来生成一个 (键, 次数)
的列表。
这样会生成一个 列表;如果你一定想要元组,可以直接在这个列表上调用 tuple()
。
示例:
>>> from collections import Counter
>>> TupleOfTuples = ( ('Venue1', 'Name1'), ('Venue1', 'Name2'), ('Venue2', 'Name3'), ('Venue3', 'Name4'), ('Venue3', 'Name5'), ('Venue3', 'Name6') )
>>> Counter(t[0] for t in TupleOfTuples).items()
[('Venue1', 2), ('Venue3', 3), ('Venue2', 1)]