How to get count dict of items but maintain the order in which they appear?

前端 未结 3 1472
悲&欢浪女
悲&欢浪女 2020-11-30 14:29

For example, I need to count how many times a word appears in a list, not sorted by frequency but with the order in which the words appear, i.e. insertion order.

<         


        
3条回答
  •  自闭症患者
    2020-11-30 15:05

    In Python 3.6, dictionaries are insertion ordered, but this is an implementation detail.

    In Python 3.7+, insertion order is guaranteed and can be relied upon. See Are dictionaries ordered in Python 3.6+? for more details.

    So, depending on your Python version, you may wish to just use Counter as is, without creating an OrderedCounter class as described in the documentation. This works because Counter is a subclass of dict, i.e. issubclass(Counter, dict) returns True, and therefore inherits the insertion ordering behaviour of dict.

    String representation

    It is worth noting the the string representation for Counter, as defined in the repr method, has not been updated to reflect the change in 3.6 / 3.7, i.e. print(Counter(some_iterable)) still returns items from largest counts descending. You can trivially return the insertion order via list(Counter(some_iterable)).

    Here are some examples demonstrating the behaviour:

    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
    

    Exceptions

    You should not use a regular Counter if additional or overwritten methods available to OrderedCounter are important to you. Of particular note:

    1. OrderedDict and consequently OrderedCounter offer popitem and move_to_end methods.
    2. Equality tests between OrderedCounter objects are order-sensitive and are implemented as list(oc1.items()) == list(oc2.items()).

    For example, equality tests will yield different results:

    Counter('xy') == Counter('yx')                # True
    OrderedCounter('xy') == OrderedCounter('yx')  # False
    

提交回复
热议问题