【问题标题】:How to get the python Counter output ordered by order of inputs?如何获得按输入顺序排序的python Counter输出?
【发布时间】:2016-08-16 21:41:23
【问题描述】:

我一直在努力获取计数(频率),然后对其进行图形表示。

我使用 python 使用来自collectionsCounter 类。我希望Counter 的输出按先到对象的顺序排列。

例如:

offset=['a','b','c','a','b','b','b','c','c','c','c','c']
counts = Counter(offset)
print counts

输出是:

Counter({'c': 6, 'b': 4, 'a': 2})

因为我希望输出如下,按照先到对象的顺序:

Counter({'a': 2, 'b': 4, 'c': 6})

这可能吗?

谢谢

【问题讨论】:

标签: python python-2.7 output counter


【解决方案1】:

OrderedCounter(2 行长)多重继承

以下精彩演讲Super considered super by Raymond Hettinger 我们可以使用多重继承:

from collections import OrderedDict, Counter

class OrderedCounter(Counter, OrderedDict):
    pass

并使用它:

>>> counter = OrderedCounter("abracadabra")
>>> for key, value in counter.items():
...    print key, value
a 5
b 2
r 2
c 1
d 1

这就是您完成任务所需的全部内容。

修正了一个稍微令人困惑的表示

让我们做更多的测试,看看我们得到了什么“结果”:

>>> counter = OrderedCounter("cbaaa")
>>> counter
OrderedCounter({'a': 3, 'c': 1, 'b': 1})

哦 - 这看起来不对,预期的顺序是“c”、“b”、“a”。让我们测试它打印键和值:

>>> for key, value in counter.items():
...    print key, value
c 1
b 1
a 3

这看起来是正确的(这正是在您的代码中使用真正重要的东西)。

事实证明,我们创建的类只是产生了一些令人困惑的表示。

这可以解决:

class OrderedCounter(Counter, OrderedDict):
    def __repr__(self):
        return "%s(%r)" % (self.__class__.__name__, OrderedDict(self))

使用时:

>>> counter = OrderedCounter("cbaaa")
>>> counter
OrderedCounter({'c': 1, 'b': 1, 'a': 1})

Raymond Hettinger 演讲的完整版(添加酸洗)

演讲中提供的完整版本增加了一种方法__reduce__,它允许酸洗 对象正确。

from collections import OrderedDict, Counter

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

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

无论如何,在大多数情况下,您将使用OrderedCounter 类的最简单版本进行管理。

【讨论】:

    【解决方案2】:

    编辑

    对不起,我误会了。尝试这个。 我使用队列概念实现了这一点。

    q = []
    ret = []
    for i in offset:
      if q.count(i)==0: q.insert(i, 0)
    while len(q):
      item = q.pop()
      ret.append((item, d.get(item)))
    print(ret)
    

    【讨论】:

    • 这如何保证输出与对象最先被计算的顺序一致?
    • 对不起。我对订购有误解。请再检查一遍
    【解决方案3】:

    python 中的字典只是哈希表,因此它们没有任何顺序。您永远无法打印出排序列表。但是您可以将它们转换为元组列表并对其进行排序。

    from collections import Counter
    import operator
    offset=['a','b','c','a','b','b','b','c','c','c','c','c']
    counts = Counter(offset)
    print(sorted(counts.items(), key=operator.itemgetter(0)))
    #[('a', 2), ('b', 4), ('c', 6)]
    

    【讨论】:

    • 对 counter 的输出进行排序并不能保证元素按照先到对象的顺序排列。
    • 我只是打印它来展示它是如何工作的。显然,如果这是他想要的,他可以将其存储为变量。
    【解决方案4】:

    您将不得不使用保证保留元素首次插入顺序的有序字典以“老式方式”执行此操作:

    from collections import OrderedDict
    
    offset = ['a','b','c','a','b','b','b','c','c','c','c','c']
    counts = OrderedDict()
    for elt in offset:
        try:
            counts[elt] += 1
        except KeyError:
            counts[elt] = 1
    
    print(counts)
    

    结果:

    OrderedDict([('a', 2), ('b', 4), ('c', 6)])
    

    【讨论】:

    • 这不是一种“老式”的方式。如果没有有序的字典,你还能如何做得更好?
    • 加一个,因为它是唯一符合元素首次计数顺序的答案。
    • 呵呵,谢谢——我所说的“老式方式”是指不用像计数器这样的高阶函数。
    【解决方案5】:

    你可以使用这样的方法:

    from collections import Counter
    offset=['a','b','c','a','b','b','b','c','c','c','c','c']
    counts = Counter(offset)
    
    for letter in offset:
        if letter in counts:
            print (letter + ": " + str(counts[letter]))
            counts.pop(letter)
    

    效果如下:

    >>> ================================ RESTART ================================
    >>> 
    a: 2
    b: 4
    c: 6
    

    您可以将配对存储在列表中,而不是打印。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-01
      • 1970-01-01
      • 2019-05-29
      • 2019-11-22
      • 1970-01-01
      • 1970-01-01
      • 2019-12-04
      相关资源
      最近更新 更多