【问题标题】:Faster Python List Comprehension更快的 Python 列表理解
【发布时间】:2018-06-29 16:17:12
【问题描述】:

我有一段代码在我的项目中运行了数千次:

def resample(freq, data):
    output = []
    for i, elem in enumerate(freq):
        for _ in range(elem):
            output.append(data[i])
    return output

例如。 resample([1,2,3], ['a', 'b', 'c']) => ['a', 'b', 'b', 'c', 'c', 'c']

我想尽可能加快速度。似乎列表理解可能会更快。我试过了:

def resample(freq, data):
   return [item for sublist in [[data[i]]*elem for i, elem in enumerate(frequencies)] for item in sublist]

这既可怕又缓慢,因为它会构建列表然后将其展平。有没有办法通过一个快速的行列表理解来做到这一点?或者可能是 numpy 的东西?

提前致谢!

编辑:答案不一定需要消除嵌套循环,最快的代码是最好的

【问题讨论】:

  • 列表推导并不比等效的 for 循环快,因为它们执行完全相同的操作。
  • 只要使用[e for i, e in enumerate(y) for j in range(x[i])]
  • 你在说什么类型的输入?如果freq 中的数字很大,那么在单个循环中使用extend 可能比append 更好
  • 我不同意关闭@jonrsharpe。它不是那个问题的重复。
  • 是的,我也不同意结案。

标签: python


【解决方案1】:

我强烈建议使用这样的生成器:

from itertools import repeat, chain
def resample(freq, data):
    return chain.from_iterable(map(repeat, data, freq))

这可能是目前最快的方法 - map()repeat()chain.from_iterable() 都是用 C 实现的,所以从技术上讲,你无法做得更好。

至于小解释:

repeat(i, n) 返回一个重复项目in 次的迭代器。

map(repeat, data, freq) 返回一个迭代器,该迭代器每次在data 的元素和freq 的元素上调用repeat。基本上是一个返回 repeat() 迭代器的迭代器。

chain.from_iterable() 将迭代器的迭代器展平以返回最终项目。

途中不会创建列表,因此没有开销,而且还有一个额外的好处 - 您可以使用 任何 类型的数据,而不仅仅是一个字符字符串。

虽然我不建议这样做,但您可以将其转换为 list(),如下所示:

result = list(resample([1,2,3], ['a','b','c']))

【讨论】:

  • 一些快速测试似乎证实这是迄今为止最快的答案。
【解决方案2】:
import itertools
def resample(freq, data):
    return itertools.chain.from_iterable([el]*n for el, n in zip(data, freq))

这样除了更快之外,还有一个懒惰的好处,它返回一个生成器,元素是一步一步生成的

【讨论】:

    【解决方案3】:

    根本不需要创建列表,只需使用嵌套循环:

    [e for i, e in enumerate(data) for j in range(freq[i])]
    
    # ['a', 'b', 'b', 'c', 'c', 'c']
    

    您可以通过删除括号轻松地使它变得懒惰:

    (e for i, e in enumerate(data) for j in range(freq[i]))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多