5

例如,我需要计算一个单词在列表中出现的次数,不是按频率排序,而是按单词出现的顺序,即插入顺序。

from collections import Counter

words = ['oranges', 'apples', 'apples', 'bananas', 'kiwis', 'kiwis', 'apples']

c = Counter(words)

print(c)

所以而不是:{'apples': 3, 'kiwis': 2, 'bananas': 1, 'oranges': 1}

我宁愿得到:{'oranges': 1, 'apples': 3, 'bananas': 1, 'kiwis': 2}

而且我真的不需要这种Counter方法,任何能产生正确结果的方法对我来说都可以。

4

4 回答 4

11

您可以使用使用and的配方collections.Countercollections.OrderedDict

from collections import Counter, OrderedDict

class OrderedCounter(Counter, OrderedDict):
    'Counter that remembers the order elements are first encountered'

    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))

    def __reduce__(self):
        return self.__class__, (OrderedDict(self),)

words = ["oranges", "apples", "apples", "bananas", "kiwis", "kiwis", "apples"]
c = OrderedCounter(words)
print(c)
# OrderedCounter(OrderedDict([('oranges', 1), ('apples', 3), ('bananas', 1), ('kiwis', 2)]))
于 2014-05-19T21:39:22.387 回答
7

在 Python 3.6+ 上,dict现在将保持插入顺序。

所以你可以这样做:

words = ["oranges", "apples", "apples", "bananas", "kiwis", "kiwis", "apples"]
counter={}
for w in words: counter[w]=counter.get(w, 0)+1
>>> counter
{'oranges': 1, 'apples': 3, 'bananas': 1, 'kiwis': 2}

不幸的是,Python 3.6 和 3.7 中的 Counter 不显示它维护的插入顺序;相反,按最常见到最不常见__repr__ 对返回进行排序。

但是您可以使用相同的 OrderedDict配方,但只需使用 Python 3.6+ dict 代替:

from collections import Counter

class OrderedCounter(Counter, dict):
    'Counter that remembers the order elements are first encountered'
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, dict(self))

    def __reduce__(self):
        return self.__class__, (dict(self),)

>>> OrderedCounter(words)
OrderedCounter({'oranges': 1, 'apples': 3, 'bananas': 1, 'kiwis': 2})

或者,由于 Counter 是dictPython 3.6+ 中维护顺序的子类,因此您可以__repr__通过调用.items()counter 或将 counter 转回 a来避免使用 Counter dict

>>> c=Counter(words)

该计数器的此演示文稿按最常见元素排序到最少,并使用 Counters__repr__方法:

>>> c
Counter({'apples': 3, 'kiwis': 2, 'oranges': 1, 'bananas': 1})

此演示文稿如遇到,或插入顺序:

>>> c.items()
dict_items([('oranges', 1), ('apples', 3), ('bananas', 1), ('kiwis', 2)])

或者,

>>> dict(c)
{'oranges': 1, 'apples': 3, 'bananas': 1, 'kiwis': 2}
于 2018-07-14T15:50:47.790 回答
1

Python 3.6中,字典是按插入顺序排列的,但这是一个实现细节。

Python 3.7+中,插入顺序得到保证并且可以依赖。请参阅Python 3.6+ 中是否对字典进行了排序?更多细节。

因此,根据您的 Python 版本,您可能希望按Counter原样使用,而无需创建文档OrderedCounter中描述的类。这是有效的,因为它是 的子类,即返回,因此继承了 的插入排序行为。Counterdictissubclass(Counter, dict)Truedict

字符串表示

值得注意的是,该方法Counter中定义的字符串表示形式尚未更新以反映 3.6 / 3.7 中的更改,即仍然从最大计数降序返回项目。您可以通过简单地返回插入订单。reprprint(Counter(some_iterable))list(Counter(some_iterable))

以下是一些演示该行为的示例:

x = 'xyyxy'
print(Counter(x))         # Counter({'y': 3, 'x': 2}), i.e. most common first
print(list(Counter(x)))   # ['x', 'y'], i.e. insertion ordered
print(OrderedCounter(x))  # OC(OD([('x', 2), ('y', 3)])), i.e. insertion ordered

例外

Counter如果可用的附加或覆盖方法OrderedCounter对您很重要,则不应使用常规方法。特别注意:

  1. OrderedDict并因此OrderedCounter提供popitemmove_to_end方法。
  2. 对象之间的相等测试OrderedCounter是顺序敏感的,并且被实现为list(oc1.items()) == list(oc2.items()).

例如,相等性测试会产生不同的结果:

Counter('xy') == Counter('yx')                # True
OrderedCounter('xy') == OrderedCounter('yx')  # False
于 2018-09-04T23:28:57.210 回答
0

在评论中解释

text_list = ['oranges', 'apples', 'apples', 'bananas', 'kiwis', 'kiwis', 'apples']


# create empty dictionary
freq_dict = {}
 
# loop through text and count words
for word in text_list:
    # set the default value to 0
    freq_dict.setdefault(word, 0)
    # increment the value by 1
    freq_dict[word] += 1
 
print(freq_dict )
{'oranges': 1, 'apples': 3, 'bananas': 1, 'kiwis': 2}

[Program finished]
于 2021-03-29T04:45:23.853 回答