有效地构建数字和列表的列表理解

Posted

技术标签:

【中文标题】有效地构建数字和列表的列表理解【英文标题】:Efficiently build a list comprehnsion of numbers and lists 【发布时间】:2018-02-21 19:18:51 【问题描述】:

我有一个函数列表。每个函数可以返回一个浮点数或 2 个浮点数的列表。我需要使用列表理解构建一个平面结果列表。 出于效率原因,我需要使用一次迭代来构建结果。出于同样的原因,for 循环不是一个选项(这是我的信念……这是正确的吗?)。

输入:

funcs=[[function_1, arguments_function_1],[function_2,arguments_function_2]...[function_n, arguments_function_n]

其中 function_j 是先前定义的函数。 arguments_function_j 是 funtion_j 的参数列表。

暂定调用:

results=[f[0](f[1]) for f in funcs]  

上面的调用在语法上是正确的,但没有以我需要的格式返回结果。事实上,假设第四个函数返回一个列表,最终结果将是

[1,2,3,[4,5],6] instead of  [1,2,3,4,5,6] as I need

我尝试了以下方法:

results=[f[0](f[1]) if type(f[0](f[1]))==float\ 
else f[0](f[1])[0],f[0](f[1])[1]\
for f in funcs]  

f[0](f[1])[0],f[0](f[1])[1] 部分在语法上不正确。它应该放在括号之间,但它不会解决问题。

有什么提示吗? 提前致谢

【问题讨论】:

Making a flat list out of list of lists in Python的可能重复 请检查原始问题是否回答了您的问题。 这些问题应该会有所帮助: - ***.com/questions/1077015/… - ***.com/questions/21418764/… 嗨,是的,我读过那篇文章,但它不能解决我的问题。那里建议的解决方案假定所有元素都是像 l=[[1],[2],[3,4],[5]] 这样的列表。我的情况不同。在我的情况下,输入是 l=[1,2,[3,4],5] 并且建议的解决方案会出现错误。 【参考方案1】:

您可以使用辅助函数通过推导式创建它,但不要忘记将它与循环计时,看看您是否真的获得了性能。

import collections
def sequencify(x):
  return x if isinstance(x, collections.Sequence) else (x,)
results = [x for (f, a) in funcs for x in sequencify(f(a))]

您还可以测试将sequencify 更改为您的特定用例是否会使其更快,例如

sequencify = lambda x: (x,) if type(f) == float else x

但是,实际上,如果您正在寻找性能,请考虑修改函数以返回具有 1 个浮点数而不是仅浮点数的元组,然后您就不需要昂贵的类型检查,并且可以使用标准的列表展平技术:

results = [x for (f, a) in funcs for x in f(a)]

编辑 - 我的快速测试表明,返回浮点数元组比浮点数列表快近 25%:

$ python3 -m timeit -s 'import random; funcs=[ (random.choice([lambda a: [a], lambda a: [a,a]]),random.random()) for i in range(10000) ]' 'result=[x for (f, a) in funcs for x in f(a)]'
100 loops, best of 3: 2.98 msec per loop

$ python3 -m timeit -s 'import random; funcs=[ (random.choice([lambda a: (a,), lambda a: (a,a)]),random.random()) for i in range(10000) ]' 'result=[x for (f, a) in funcs for x in f(a)]'
100 loops, best of 3: 2.27 msec per loop

【讨论】:

酷!事实上,总是返回一个列表是最有效的解决方案。谢谢!!!! 使用元组而不是列表,效果更好,速度更快。非常感谢【参考方案2】:

你只需要链接你的价值观,而不是

results=[f[0](f[1]) for f in funcs]  

只是做

import itertools
result = list(itertools.chain.from_iterable(f[0](f[1]) for f in funcs))

(这将使您的结果列表变平,包裹在list 中以强制迭代)

另请参阅:Making a flat list out of list of lists in Python

【讨论】:

以上是关于有效地构建数字和列表的列表理解的主要内容,如果未能解决你的问题,请参考以下文章

深入理解Python列表(list)

列表理解有效,但 for 循环无效——为啥?

更好地理解堆栈和列表

当我尝试插入由列表理解生成的元组列表时,executemany 抛出错误;如果它是硬编码的,则相同的列表有效

从大型元组/行列表中有效地构建 Pandas DataFrame

从大型元组/行列表中有效地构建 Pandas DataFrame