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

如何在for循环中修改列表值

  •  1
  • Dave  · 技术社区  · 3 月前

    In How to modify list entries during for loop? ,一般建议是,它可能是不安全的,所以除非你知道它是安全的,否则不要这样做。在第一个答案下的评论中@martineau说:

    它(循环变量)不会复制。它只是将循环变量名赋给 被迭代对象的连续元素或值。

    这是我期望和想要的行为,但我没有得到它。我想删除尾随 None s来自列表中的每个值。我的循环变量修改正确,但列表元素保持不变。

    如何获取循环变量 fv 作为指向列表行的指针 foo ,不是行的副本吗?

    额外加分:我的代码很糟糕,不符合Python,所以最好使用理解式或切片而不是for循环的解决方案。

    foo = [
        ['a', 'b', None, None],
        ['c', None, 'e', None],
        ['f', None, None, None]
    ]
    
    desired = [
        ['a', 'b'],
        ['c', None, 'e'],
        ['f']
    ]
    
    for fv in foo:
        for v in range(len(fv) -1, 0, -1):
            if fv[v] == None:
                fv = fv[:v]
                print(f' {v:2} {fv}')
            else:
                break
    print(foo)
    

    输出为:

      3 ['a', 'b', None]
      2 ['a', 'b']
      3 ['c', None, 'e']
      3 ['f', None, None]
      2 ['f', None]
      1 ['f']
    [['a', 'b', None, None], ['c', None, 'e', None], ['f', None, None, None]]
    
    1 回复  |  直到 3 月前
        1
  •  2
  •   Selcuk    3 月前

    线 fv = fv[:v] 将创建一个名为的新变量 fv 而不是变异 fv 。你应该修改现有的列表。

    一种解决方案是使用 while 删除不需要的值,直到没有值为止。这个 .pop() method 会变异 row 而不是返回一个新列表:

    for row in foo:
        while row and row[-1] is None:
            row.pop()
    
    assert foo == desired
    
        2
  •  0
  •   Валерий Аббакумов    3 月前

    您可以从列表末尾删除从第一个非零元素开始的一系列元素。这种方法更快,然后@Selcuk回答

    for row in foo:
        last_null_index = 0
        for index, element in enumerate((reversed(row))):
            if element is not None:
                last_null_index = index
                break
        
        # for case when all of elements is not None
        if last_null_index == 0:
            continue
    
        row[-last_null_index:] = []
    
    assert foo == desired