代码之家  ›  专栏  ›  技术社区  ›  greybeard

如何从两端迭代序列?

  •  2
  • greybeard  · 技术社区  · 7 年前


    int start = 2, beyond = 7;
    for (int forward = start, back = beyond ; forward <= --back ; forward++)
        printf("%d %d\n", forward, back);
    

    我似乎无法决定我最不喜欢以下哪种变体:

    seq = tuple(chr(c) for c in range(ord('a'), ord('z')+1))
    start, beyond = 2, 7
    
    print("subtract")
    for forward in range(start, beyond):
        back = start + beyond - 1 - forward
        if (back < forward):
            break
        print(seq[forward], seq[back])
    #    if (back <= forward): XXX ERROR, as YvesgereY pointed out
    #        break
    print("reversed")
    for forward, back in zip(range(start, beyond),
                             reversed(range(start, beyond))):
        if (back < forward):
            break
        print(seq[forward], seq[back])
    print("step -1")
    for forward, back in zip(range(start, beyond), range(beyond-1, start-1, -1)):
        if (back < forward):
            break
        print(seq[forward], seq[back])
    print("naked code")
    forward, back = start, beyond-1 # thanks again, YvesgereY
    while (forward <= back):
        print(seq[forward], seq[back])
        forward += 1
        back -= 1
    

    有没有一种令人愉快/理智/惯用的方法来处理这个问题?

    5 回复  |  直到 7 年前
        1
  •  4
  •   cs95    7 年前

    为什么不呢? zip

    mid = (len(lst) + 1) // 2   
    for x, y in zip(lst[:mid], lst[::-1]):
         print((x, y))
    
    (1, 5)
    (2, 4)
    (3, 3)
    

    拉链

        2
  •  4
  •   YvesgereY    7 年前

    我宁愿写:

    size = max((beyond-start+1)//2,0)  # 0 if start>beyond
    for i in range(0,size):
       print(start+i,beyond-i-1)
    

    substract step -1 版本不正确,因为它们允许 forward>back 在最后一次迭代中。

    while 强调循环条件的版本(减少一个错误的可能性):

    forward, back = start, beyond-1
    while forward <= back:
        print(forward, back)
        forward += 1
        back -= 1
    
        3
  •  3
  •   Chris    7 年前

    在我看来,最后一种使用while循环的方法是最好的:

    forward, back = start, beyond
    while (forward < back):
        back -= 1
        print(forward, back)
        forward += 1
    

    它简洁但仍然可读,具有清晰的语义,与其他具有多个级别的函数调用嵌套的方法相比,它似乎是最“Pythonic”的方法。您可以通过将其包装在生成器中进行改进:

    def iterate_to_middle(start_front, start_end):
        while start_front < start_end:
            start_end -= 1
            yield start_front, start_end
            start_front += 1
    

    >>> for indexes in iterate_to_middle(2, 7):
        print(indexes)
    
    
    (2, 6)
    (3, 5)
    (4, 4)
    
        4
  •  3
  •   Moses Koledoye    7 年前

    while 回路正常。

    负索引 enumerate 要为每个转发项生成负的对应索引:

    lst = [1, 2, 3, 4, 5]
    
    for i, x in enumerate(lst, 1):
        print(x, lst[-i])
        if i * 2 >= len(lst): break
    

    (1, 5)
    (2, 4)
    (3, 3)
    
        5
  •  1
  •   Wes Williams    3 年前

    可以使用~运算符获取(索引+1)*-1。

    arr = [1, 2, 3, 4, 5]
    for i in range((len(arr) + 1) // 2):
        print(arr[i], arr[~i])
    
    1 5
    2 4
    3 3