我正在尝试按照OrderedCounter输出中显示的顺序打印出Key Value对。
from collections import Counter, OrderedDict
class OrderedCounter(Counter, OrderedDict):
pass
c = OrderedCounter('supernatural')
print c
我得到以下输出:
OrderedCounter({'u': 2, 'r': 2, 'a': 2, 's': 1, 'p': 1, 'e': 1, 'n': 1, 't': 1, 'l': 1})
有没有办法只打印出第一个键值对?
我基本上是在尝试打印给定字符串中的第一个重复字符。
答案 0 :(得分:4)
问题在于__repr__
被第一个超类使用(因为你不会覆盖它),那就是Counter
。 Counter
的表示形式是按降序排列值。您将OrderedDict
和sorted
子类化为稳定的事实会使"u"
成为第一个元素。
但是,Counter
并未提供__iter__
方法,因此您只需使用__iter__
OrderedDict
即可保留插入顺序:
>>> next(iter(c.items()))
('s', 1)
要获得第一个重复的角色,只需使用理解:
>>> next((key, value) for key, value in c.items() if value > 1)
('u', 2)
(使用Python2,您可能希望使用iteritems()
而不是items()
)
要打印第一个最常见的值,您可以使用Counter.most_common
方法:
>>> c.most_common(1)
[('u', 2)]
答案 1 :(得分:2)
此任务您不需要Count
或OrderedDict
。这是一种优化方法(对于长度为n
的字符串,复杂度为O(n)):
In [35]: def first_repeated(s):
seen = set()
for i, j in enumerate(s):
if j in seen: # membership check in set is O(1)
return j, s.count(j, i + 1) + 2
seen.add(j)
....:
In [36]: first_repeated(s)
Out[36]: ('u', 2)
以下是其他答案的基准测试,表明此方法的速度提高了近4-5倍:
In [39]: def counter_based(s):
....: c = Counter(s)
....: return next(key for key in c if c[key] > 1)
....:
In [40]: %timeit counter_based(s)
100000 loops, best of 3: 5.09 us per loop
In [41]: %timeit first_repeated(s)
1000000 loops, best of 3: 1.71 us per loop
如果您想对大量数据执行此操作,您还可以使用suffix tree更快地执行此任务。以下是我自己在github中对此算法的优化实现。如果您不熟悉此数据结构和算法https://github.com/kasramvd/SuffixTree
,您还可以使用文档和有用的链接作为在生成器表达式中使用str.counter
的另一个基于线性的答案,您可以使用@Stefan Pochmann建议的以下方法:
next((c, s.count(c)) for c in s if s.count(c) > 1)
答案 2 :(得分:-1)
根据我的理解,我认为你正在寻找这样的东西:
print c.most_common()[0]
这会输出('u', 2)
答案 3 :(得分:-1)
如果您需要在某个地方使用该计数器,则可以对其进行过滤和排序以获得您正在寻找的内容:
from collections import Counter
input_string = 'supernatural'
c = Counter(input_string)
print sorted((pair for pair in c.items() if pair[1]>1), key=lambda x: input_string.index(x[0]))[0]
我们将计数器过滤为仅返回出现多次的字母,根据其在输入字符串中的位置对其进行排序,并返回我们找到的第一对。因此,这会打印('u', 2)