Python - zip(跳过一个列表中的元素但不跳过另一个列表中的元素)

4
我有两个列表,ab。假设 len(a) = len(b) + 1。我想同时遍历这两个列表,并设置条件。由于 a 有额外的垃圾值,它应该跳过 a 中的该值,但不应该跳过 b 中的该值。接下来进行下一次迭代时,a 应从下一个元素开始,而 b 应从同一个初始元素开始。
在示例中进行解释。
a = [1,2,3,4,5,6,19,20]
b = [7,8,9,10,11,17,18]

for x,y in zip(a,b):
    if x == 5: # some condition
        #in this case y is 11
        continue # skip the value 5 from a but dont skip 11 from b.
    print x,y

预期输出结果是:
1 7
2 8
3 9
4 10
6 11 # 5 skipped because of some condition, but 11 remains intact
19 17
20 18

我该如何去做呢?

或者如果还有其他解决方案,同时迭代,请告诉我。


你能展示一下预期的输出吗? - Mazdak
2个回答

5

如果你在循环过程中不知道要跳过哪个值,可以使用迭代器,并调用next来丢弃一个值:

import itertools

a = [1,2,3,4,5,6,19,20]
b = [7,8,9,10,11,17,18]

it_a = iter(a)
it_b = iter(b)

for x,y in itertools.izip(it_a, it_b):
    if x == 5:
        x = next(it_a)
    print x,y

这将得到:

1 7
2 8
3 9
4 10
6 11
19 17
20 18

请注意,如果您调用next(it_a),并且已经读取了从a的迭代器中的所有值,则会收到StopIteration异常,并且您可能希望以某种方式处理它。另外,请注意,如果您在某种方式下跳过了两个a元素,则a的元素将在b之前用完,而zip将在产生b的最后一个元素之前静默停止。
或者,如果您在进入for循环之前确实知道要排除什么,您可以使用生成器推导式而不是列表推导式做基本上相同的事情。这将延迟执行排除操作:
a = [1,2,3,4,5,6,19,20]
b = [7,8,9,10,11,17,18]

it_a = (x for x in a if x not in {5, 42, 101})

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

2

我认为最简单的方法是在压缩之前直接剪掉"垃圾"。

>>> a = [1,2,3,4,5,6,19,20]
>>> b = [7,8,9,10,11,17,18]
>>> a.remove(5)
>>> a
[1, 2, 3, 4, 6, 19, 20]
>>> zip(a,b)
[(1, 7), (2, 8), (3, 9), (4, 10), (6, 11), (19, 17), (20, 18)]
>>>

如果您的条件比一个值更复杂,您可以像这样操作:
>>> a = (i for i in a if not i in list_of_excluded_values)

最后,正如评论中sweeneyrod所指出的那样,您可以在使用a_trimmed = a[:] 去除垃圾之前先复制a


1
如果需要,您可以在删除列表之前将其复制,以便它不会被改变。 - rlms
1
@user1162512 你可以将那个列表推导式转换成生成器推导式,这样就可以实现惰性排除。 - jme
有没有更好的方法? - Praful Bagai
@user1162512,我现在明白了,如果性能是一个很大的关注点,那么你应该像jme的回答中所提到的那样使用迭代器。 - wnnmaw
@jme,不需要删除你的答案,我很喜欢它,非常聪明。 - wnnmaw
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接