在列表理解中添加额外的项目

时间:2018-05-24 08:44:57

标签: python list list-comprehension

我有这样的清单:

a = ['orange', 'apple', 'banana']

从此我使用简单的列表理解构建了另一个元组列表:

b = [(key, key.upper()) for key in a]

结果是这样的:

b = [('orange', 'ORANGE'), ('apple', 'APPLE'), ('banana', 'BANANA')]

现在我需要在新生成的b列表的开头(或者例如末尾)插入另一个元组:('---', None)

两个简单的解决方案是:

# Solution 1
b = [('---', None)] + b

# Solution 2 
b.insert(0, ('---', None))

问题:
有没有办法直接从列表推导构造中完成同样的事情?
可以在python中使用这样的(伪代码)吗?

b = [('---', None), (key, key.upper()) for key in a]

3 个答案:

答案 0 :(得分:9)

是的,通过使用生成器理解:

b = [('---', None), *((key, key.upper()) for key in a)]

可以使用列表理解,而不是使用生成器理解。使用生成器理解的好处是他们不会创建新列表,而是逐个分发项目。如果您的列表(a)很大,则会对内存使用和/或性能产生影响。

使用星号(" splat运算符")解压缩这样的序列是PEP 448 — Additional Unpacking Generalizations。它允许您不仅在函数调用中使用*,而且在列表,生成器和集合理解中使用**(同样适用于if和字典理解)。

答案 1 :(得分:4)

过早优化是万恶之源

您确定的操作很可能您的瓶颈。使用允许您使用一个表达式的聪明列表理解并不能解决与性能相关的问题。以下是列表中包含3mio项目的演示。

如果您需要重复将项目添加到左侧列表中,我建议您使用collections.deque。请注意,deque appendleft的复杂度为O(1),而insert(0, value)的列表的O(n)性能为O(n)。

from collections import deque

a = ['orange', 'apple', 'banana']*1000000

def l3v(a):
    return [('---', None), *((key, key.upper()) for key in a)]

def jpp(a):
    b = deque([(key, key.upper()) for key in a])
    b.appendleft(('---', None))
    return list(b)

def original(a):
    return [('---', None)] + [(key, key.upper()) for key in a]

def original2(a):
    b = [(key, key.upper()) for key in a]
    b.insert(0, ('---', None))
    return b

%timeit l3v(a)        # 1.35 s per loop
%timeit jpp(a)        # 1.23 s per loop
%timeit original(a)   # 1.17 s per loop
%timeit original2(a)  # 1.14 s per loop

答案 2 :(得分:1)

尝试使用列表推导的if else。如下所示

b = [(a[i],a[i].upper()) if i < len(a) else ('---',None)  for i in range(len(a)+1)]

希望它有所帮助。

快乐编码:)