在有序计数器中打印第一个键值

时间:2017-02-15 11:11:21

标签: python python-2.7 python-collections

我正在尝试按照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})

有没有办法只打印出第一个键值对?

我基本上是在尝试打印给定字符串中的第一个重复字符。

4 个答案:

答案 0 :(得分:4)

问题在于__repr__被第一个超类使用(因为你不会覆盖它),那就是CounterCounter的表示形式是按降序排列值。您将OrderedDictsorted子类化为稳定的事实会使"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)

此任务您不需要CountOrderedDict。这是一种优化方法(对于长度为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)