迭代两个列表并将它们同步

3
我需要按以下方式迭代两个列表:
伪代码:
j=1
for i=1 to n:
   print a[i], b[j]
   while b[j+1] <= a[i]:
      j++
      print a[i], b[j]

例如:

a = [1 3 5 7]
b = [2 4 9] 

期望输出:
1 2
3 2
5 2
5 4
7 4

你如何在Python中干净地完成它?

3
这个问题对我来说似乎不完整,您能否根据这两个输入列表解释一下您的输出?数字 "9" 发生了什么事情? - Levon
@Levon,伪代码的输出中没有显示数字9,但我的Python翻译中有显示。 - murgatroid99
2个回答

7
您的伪代码几乎可以在Python中工作。以下是一些可行的代码,可以实现您想要的功能:
a = [1, 3, 5, 7]
b = [2, 4, 9] 
j = 0
for i in range(len(a)):
    print a[i], b[j]
    while j<len(b)-1 and b[j+1] <= a[i]:
        j += 1
        print a[i], b[j]

请注意以下几点进行Python翻译:
  1. 在声明列表时,需要在项目之间使用逗号。
  2. 列表索引从0开始,因此i和j都应该从0开始。
  3. len(a)返回a的长度(在本例中为4),通过将i迭代到range(len(a))中,可以执行循环,从0到len(a)-1的每个整数,这是a中的所有索引。
  4. Python不支持++操作,因此我们改用j + = 1。
  5. 我们必须避免使用超出b范围的索引,因此我们在增加j之前测试以确保j仍在范围内。
通过以下方式,可以使此代码更符合Pythonic:
a = [1, 3, 5, 7]
b = [2, 4, 9] 
j = 0
for element in a:
   print element, b[j]
   while j<len(b)-1 and b[j+1] <= element:
      j += 1
      print element, b[j]

通常情况下,您可能不只是想打印列表元素,因此为了更一般的用例,您可以创建一个生成器,例如:

def sync_lists(a, b)
    if b:
        j = 0
        for element in a:
            yield (element, b[j])
            while j<len(b)-1 and b[j+1] <= element:
                j += 1
                yield (element, b[j])

然后,您可以像以前一样使用打印它们的方式进行打印。
a = [1, 3, 5, 7]
b = [2, 4, 9]
for (e1, e2) in sync_lists(a, b):
    print e1, e2

是的,这似乎很不寻常,直接翻译伪代码可能比使用“next”和“itertools”的某些技巧更简单。我可能会将这个迭代逻辑封装在生成器中,因为对我来说,这是奇怪的迭代逻辑最符合Python风格的"家"。 - DSM
我很好奇 - 你建议使用 enumerate,但是看起来你没有使用 i。直接遍历列表不是更容易吗? - Sam Mussmann
@SamMussmann 没错,我漏掉了那个。出于某种原因,我还以为我仍然需要对 a 进行索引。 - murgatroid99

2

murgatroid99的回答中的生成器代码可以通过使用next()而不是索引算术来推广到任何可迭代对象(而不仅仅是序列):

def sync_list(a, b):
    b = iter(b)
    y, next_y = next(b), next(b)
    for x in a:
       yield x, y
       while next_y <= x:
          y, next_y = next_y, next(b)
          yield x, y

请注意,如果使用错误的数组,可能会出现“StopIteration”异常。我修改了我的代码以避免相应的“IndexError”。 - murgatroid99
1
@murgatroid99:StopIteration 由调用者(例如 for 循环)处理。在生成器中不需要对“错误”数组进行特殊处理。 - jfs
@murgatroid99:示例调用者是 for e1, e2 in sync_lists(a, b):。它可以透明地处理 StopIteration - jfs
@SvenMarnach,由于没有给出不变量,我无法评论我的代码是否破坏了它们,但我认为你关于异常的观点是正确的。 - murgatroid99
@murgatroid99:我将所有产生的对中的 y <= x 解释为所需的不变量,但你说得对,这还没有明确定义(而且没有建议的代码片段检查第一对是否符合此条件)。 - Sven Marnach
显示剩余2条评论

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