【问题标题】:Union of many Counters多计数器联合
【发布时间】:2013-09-17 01:25:54
【问题描述】:

找到Counters 列表的并集的最佳方法是什么(就可读性和效率而言)?

例如,我的列表可能如下所示:

counters = [Counter({'a': 6, 'b': 3, 'c': 1}),
            Counter({'a': 2, 'b': 5}),
            Counter({'a': 4, 'b': 4}),
            ...]

我要计算并集,即counters[0] | counters[1] | counters[2] | ...

一种方法是这样的:

def counter_union(iterable):
    return functools.reduce(operator.or_, iterable, Counter())

有更好的方法吗?

【问题讨论】:

  • 我认为你的方法非常好。
  • 如果您有很多计数器,您可能需要使用|= 的解决方案。
  • @arshajii:嗯,我在想它会是就地的,避免了潜在的二次复制时间,但它看起来不像 Counter 实际上就地实现任何运算符的版本。
  • 这取决于 Python 版本:从 Python 3.3 开始为 Counters 实现了就地多重方法。

标签: python counter


【解决方案1】:

天哪,Python 程序员什么时候开始害怕简单的循环了?哈哈。

result = Counter()
for c in counters:
    result |= c

在现实生活中,将事物压缩成理论上尽可能少的角色确实没有奖品。嗯,是的,在 Perl 中有,但在 Python 中没有;-)

稍后:根据 user2357112 的评论,从 Python 3.3 开始,上面的代码将“就地”联合到 result。也就是说,result 真正被重用,可能在每次迭代中变得更大。

在任何拼写中

counters[0] | counters[1] | counters[2] | ...

相反,当计算下一个部分结果时,到目前为止的整个部分结果都会被丢弃。这可能(也可能不会)慢很多。

【讨论】:

  • 你不是 timsort 的创造者,对吧?
  • 是的,但这不是偶然的 ;-)
【解决方案2】:

user2357112 和 Tim 的 cmets 让我意识到,如果你要使用 reduce,你至少应该使用 operator.ior,而不是 operator.or_。在 Python 3.3+ 中,这将避免为每次迭代创建一个新计数器。

def counter_union(iterable):
    return functools.reduce(operator.ior, iterable, Counter())

【讨论】:

    【解决方案3】:

    我认为循环更具可读性:

    def counter_union(iterable):
        union = Counter()
        for counter in counters:
            union |= counter
        return union
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多