最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - How do I modify a list value in a for loop - Stack Overflow

programmeradmin0浏览0评论

In How to modify list entries during for loop?, the general recommendation is that it can be unsafe so don't do it unless you know it's safe. In comments under the first answer @martineau says:

It [the loop variable] doesn't make a copies. It just assigns the loop variable name to successive elements or value of the thing being iterated-upon.

That is the behavior I expect and want, but I'm not getting it. I want to remove trailing Nones from each value in the list. My loop variable is modified correctly but the list elements remain unchanged.

How can I get the loop variable fv to be a pointer to the rows of list foo, not a copy of the row?

Extra credit: my code is sucky non-pythonic, so a solution using comprehensions or slices instead of for loops would be preferred.

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)

The output is:

  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]]

In How to modify list entries during for loop?, the general recommendation is that it can be unsafe so don't do it unless you know it's safe. In comments under the first answer @martineau says:

It [the loop variable] doesn't make a copies. It just assigns the loop variable name to successive elements or value of the thing being iterated-upon.

That is the behavior I expect and want, but I'm not getting it. I want to remove trailing Nones from each value in the list. My loop variable is modified correctly but the list elements remain unchanged.

How can I get the loop variable fv to be a pointer to the rows of list foo, not a copy of the row?

Extra credit: my code is sucky non-pythonic, so a solution using comprehensions or slices instead of for loops would be preferred.

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)

The output is:

  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]]
Share Improve this question edited 14 hours ago Selcuk 59.2k12 gold badges110 silver badges115 bronze badges asked 14 hours ago DaveDave 3,9562 gold badges34 silver badges45 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 2

The line fv = fv[:v] will create a new variable named fv instead of mutating fv. You should mutate the existing list.

One solution could be using while to strip unwanted values until none left. The .pop() method will mutate row instead of returning a new list:

for row in foo:
    while row and row[-1] is None:
        row.pop()

assert foo == desired

You can go from the end of the list and remove a range of elements starting from the first non-zero element. If you have a lot of None elements (average more then 50), this approach faster, then @Selcuk answer

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
发布评论

评论列表(0)

  1. 暂无评论