4

我正在尝试以与 OrderedCounter 输出中显示的顺序相同的顺序打印出键值对。

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

4 回答 4

4

问题是__repr__第一个超类使用了它(因为你没有覆盖它),那就是Counter. 的表示Counter是它按值降序排序。OrderedDict您子类化并且稳定的事实sorted使它看起来"u"是第一个元素。

但是Counter没有提供__iter__方法,因此您将使用__iter__ofOrderedDict来简单地保持插入顺序:

>>> 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)]
于 2017-02-15T11:20:21.373 回答
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

如果您想在大量数据上执行此任务,您还可以使用后缀树更快地完成此任务。这是我自己在github中对该算法的优化实现。如果您不熟悉此数据结构和算法,也可以使用文档和有用的链接https://github.com/kasramvd/SuffixTree

作为在生成器表达式中使用的另一个基于线性的答案str.counter,您可以使用@Stefan Pochmann 建议的以下方法:

next((c, s.count(c)) for c in s if s.count(c) > 1)
于 2017-02-15T11:27:32.953 回答
-1

据我了解,我认为您正在寻找这样的东西:

print c.most_common()[0]

这给出了输出('u', 2)

于 2017-02-15T11:19:00.750 回答
-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)

于 2017-02-15T11:35:36.623 回答