单列表迭代与多列表推导

时间:2017-06-21 03:09:07

标签: python python-2.7 list-comprehension

我有一个数据列表,我需要将其中的一些元素复制到几个不同的列表中。进行列表的单次迭代或执行多个列表推导会更好吗

E.g。

def split_data(data):
    a = []
    b = []
    c = []
    for d in data:
        if d[0]   >   1 : a.append(d)
        if d[1]   == 'b': b.append(d)
        if len(d) ==  3 : c.append(d)

    return a, b, c

对战

def split_data(data):
    a = [d for d in data if d[0]   >   1 ]
    b = [d for d in data if d[1]   == 'b']
    c = [d for d in data if len(d) ==  3 ]

    return a, b, c

我知道这样做的更加pythonic的方式是使用列表推导,但在这种情况下就是这种情况吗?

3 个答案:

答案 0 :(得分:3)

在第一个示例代码中,它只需要使用多个if语句迭代数据一次,而后面的代码需要迭代数据3次。我相信列表理解将在大多数情况下以相同的迭代次数赢得数据。

对于像你的例子那样的简单操作,我更喜欢列表理解方法,当操作变得更复杂时,为了代码可读性,另一个会更好。

对2功能的一些基准测试应该会告诉你更多。 基于我对这两个函数的快速基准测试,使用一些虚拟数据集获得运行时如下。此运行时可能并非总是如此,具体取决于数据集

# without list comprehension
>>> timeit.timeit('__main__.split_data([("a","b")] * 1000000)', 'import __main__', number=1)
0.43826036048574224

# with list comprehension
>>> timeit.timeit('__main__.split_data([("a","b")] * 1000000)', 'import __main__', number=1)
0.31136326966964134

答案 1 :(得分:2)

我说这取决于。如果您的d是一个列表而且相对较小,那么您可以进行列表理解。但是,如果您的d比较大(提示%timeit是您的朋友),那么您的第一个选项只会迭代一次,因此效率会更高。

另请注意,您的第一个版本适用于所有生成器,而第二个版本不适用于使用项目的生成器。你甚至可以通过自己提供一个生成器来链接它,即使用yield a, b, c而不是return

答案 2 :(得分:2)

如果你想要更多的pythonic,我们可以参考python的禅宗。

Explicit is better than implicit.

Sparse is better than dense.

Readability counts.

虽然两者都是可读的,但我要说你的第一个例子更具可读性。如果您的data具有更多维度并且需要更多嵌套for循环,那么第一个示例将更清楚如果涉及更多逻辑,您将如何处理每个嵌套元素。

虽然Skycc的答案确实显示了更快的列表理解结果,但理想情况下你应该首先考虑可读性然后进行优化,除非你真的需要从列表理解中获得那么少的加速。