【问题标题】:What is the pythonic way to loop through two arrays at the same time?同时遍历两个数组的pythonic方法是什么?
【发布时间】:2013-01-12 13:40:54
【问题描述】:

如果我有两个长度相同的数组 - 比如说 a 和 b

a = [4,6,2,6,7,3,6,7,2,5]

b = [6,4,6,3,2,7,8,5,3,5]

通常,我会这样做:

for i in range(len(a)):
    print a[i] + b[i]

而不是这样的:

i=0
for number in a:
    print number + b[i]
    i += 1

因为我更喜欢与使用的方法保持一致。

我知道zip,但我从不使用它。这就是 zip 的用途吗?

会

for pair in zip(a,b):
    print pair[0] + pair[1]

是 pythonic 的方法吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    如果a 和b 列表很短,请使用zip(如@Vincenzo Pii 所示):

    for x, y in zip(a, b):
        print(x + y)
    

    如果a和b列表很长,那么使用itertools.izip来节省内存:

    import itertools as IT
    for x, y in IT.izip(a, b):
        print(x + y)
    

    zip 创建一个元组列表。如果 a 和 b 很大,这可能会很麻烦(内存方面)。

    itertools.izip 返回一个迭代器。迭代器不会生成完整的元组列表;它只产生 for 循环请求的每个项目。因此,它可以为您节省一些内存。

    在 Python2 中,在短名单上调用 zip(a,b) 比使用 itertools.izip(a,b) 更快。但是在 Python3 中注意 zip 默认返回一个迭代器(即它相当于 Python2 中的 itertools.izip)。


    其他感兴趣的变体:

    【讨论】:

    • 为了完成这个,我还要提到future_builtins。
    • 那么在python3中的zip和itertools.izip一样吗?还是会根据列表的大小而变化?
    • @will: 是的,Python3 中的zip 与Python2 中的itertools.izip 相同。 (它不会随着列表的大小而改变行为。)要在 Python3 中获得旧的 zip 行为,请使用 list(zip(a,b))。
    【解决方案2】:

    一个可能的解决方案是使用zip,正如您自己提到的,但与您在问题中的写法略有不同:

    for x, y in zip(a, b):
        print x, y
    

    注意zip() 返回的元组列表的长度将等于a 和b 长度之间的最小值。这会在 a 和 b 的长度不同时产生影响。

    【讨论】:

    • 从各种示例和文档页面中看起来确实非常熟悉
    • 确认它是pythonic :)!
    【解决方案3】:

    您可以使用Numpy,而不是使用zip,特别是如果速度很重要并且您有很长的数组。它更快,一旦你使用 numpy 数组,你就不需要循环,只需编写:

    print a + b
    

    图表显示了使用 zip、izip 和 numpy 对不同长度列表求和的平均时间:

    【讨论】:

    • 是的,我知道 numpy。它绝对适用于这种情况,但我给出的例子只是一个人为的例子。我真正想要的是当你有两个对象列表,并且你想访问两者的第 n 个对象时。当我想在matplotlib 饼图中将hatch 模式添加到wedges 时,这对我来说变得很明显。最终用途类似于for pattern, wedge in zip(patterns, wedges): wedge.set_hatch(pattern)
    【解决方案4】:

    由于numpy 已在另一个答案中讨论过,因此提供此答案是为了完整性,并且将更高排名数组中的值配对在一起通常很有用。

    accepted answer 适用于任何等级为 1 的序列/数组。但是,如果序列是多个级别的(例如等级为 2 或更多的numpy 数组,还例如在list lists 或 tuple tuples),需要遍历每个等级。下面是一个带有 2D numpy 数组的示例:

    import numpy as np
    a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    b = np.array([list('abc'), list('pdq'), list('xyz')])
    c = np.array([[frobnicate(aval, bval) for aval, bval in zip(arow, brow)] for arow, brow in zip(a, b)])
    

    同样的概念也适用于任何一组相同形状的二维嵌套序列:

    a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    b = [list('abc'), list('pdq'), list('xyz')]
    c = [[frobnicate(aval, bval) for aval, bval in zip(arow, brow)] for arow, brow in zip(a, b)]
    

    如果嵌套序列中的一个或两个有“洞”,使用itertools.zip_longest填充洞(填充值默认为None但可以指定):

    from itertools import zip_longest as zipl
    a = [[], [4, 5, 6], [7, 8, 9]] # empty list in the first row
    b = [list('abc'), list('pdq'), []] # empty list in the last row
    c = [[frobnicate(aval, bval) for aval, bval in zipl(arow, brow)] for arow, brow in zipl(a, b)]
    

    【讨论】:

      猜你喜欢
      • 2011-04-04
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      • 2022-08-30
      相关资源
      最近更新 更多