【问题标题】:How to change object once in a loop如何在循环中更改一次对象
【发布时间】:2019-07-28 15:23:00
【问题描述】:

我正在尝试使对象 X 成为背景,A 是要向上或向下移动的对象,但是一旦我使用循环将 A 更改为 X,循环会在下一行中找到 a 并且再做一次,我怎么做才能让它只改变一次并继续前进?

newlist = ['X','X','A','X','X','X','X']

for i in range(len(newlist)):

    print(newlist[i])

    if newlist[i] == 'A':

        newlist[i] = 'X'

        newlist[i+1] = 'A'

应该会显示

X
X
X
A
X
X
X

来自

X
X
A
X
X
X
X

但现在它显示

X
X
X
A
A
A
A

【问题讨论】:

  • newlist = ['X','X','X','X','X','X','A'] 的输出是什么
  • 这似乎是XY problem。我的意思是,如果 'A' 唯一重要的是它的位置,为什么不废弃列表并使用 int 来表示它的位置?
  • 那个输出不对。我刚刚运行了代码,得到了 2 个 X 和 5 个 A,然后是 IndexError。

标签: python loops if-statement


【解决方案1】:

在进行降档时(仅针对我自己),我发现了一种比我之前的答案更好的方法:

deque 向可迭代对象添加旋转功能。

from collections import deque

newlist = ['X', 'X', 'A', 'X', 'A', 'X', 'A']
print(f'Original:\n{newlist}')  # debug

a = deque(newlist)
b = deque(newlist)

a.rotate(1)
newlist = list(a)
print(f'Shift up:\n{newlist}')

b.rotate(-1)
newlist = list(b)
print(f'Shift down:\n{newlist}')

结果:

Original:
['X', 'X', 'A', 'X', 'A', 'X', 'A']
Shift up:
['A', 'X', 'X', 'A', 'X', 'A', 'X']
Shift down:
['X', 'A', 'X', 'A', 'X', 'A', 'X']

【讨论】:

  • 不错的选择。 deque 通过使用某种动态索引窗口有效地做到了这一点。
【解决方案2】:

代码是不言自明的。有一个if的case来检查[index+1]是否存在

list = ['X','X','A','X','X','X','X']

try:
    for el in list:
        print(list)
        if el == 'A':
            index = list.index(el)
            if list[index+1]:
                list[index+1] = el 
            list[index] = 'X'
except:
    print('Out of index!!')

结果:

C:\Desktop>python test.py
['X', 'X', 'A', 'X', 'X', 'X', 'X']
['X', 'X', 'A', 'X', 'X', 'X', 'X']
['X', 'X', 'A', 'X', 'X', 'X', 'X']
['X', 'X', 'X', 'A', 'X', 'X', 'X']
['X', 'X', 'X', 'X', 'A', 'X', 'X']
['X', 'X', 'X', 'X', 'X', 'A', 'X']
['X', 'X', 'X', 'X', 'X', 'X', 'A']
Out of index!!

【讨论】:

  • 永远不要使用内置类型list 命名变量。另外,不要调用.index - 使用for i, el in enumerate(ls)
【解决方案3】:

更改后只需使用命令break

newlist = ['X','X','A','X','X','X','X']

for i in range(len(newlist)):

    if newlist[i] == 'A':

        newlist[i] = 'X'

        newlist[i+1] = 'A'

        break
print " ". join(newlist)

继续

newlist = ['X','X','A','X','X','X','X']
k = -1
for i in range(len(newlist)):

    if k == i:
        continue

    if newlist[i] == 'A':

        newlist[i] = 'X'

        newlist[i+1] = 'A'

        k = i+1
print " ". join(newlist)

【讨论】:

  • 如果newlist = ['X','X','A','X','A','X','X']怎么办?
  • 然后使用命令 continue 代替下一个值。
【解决方案4】:

使用itertools.islicenext(),您可以操作可迭代对象。
感谢我的消息来源:How do I skip a few iterations in a for loop

还在最后处理了一个“A”,并与列表中的几个“A”一起使用。

from itertools import islice

newlist = ['X', 'X', 'A', 'X', 'A', 'X', 'A']
print(newlist)  # debug

numbers = iter(range(len(newlist)))

for i in numbers:
    if newlist[i] == 'X':
        print(newlist[i])

    if newlist[i] == 'A':
        newlist[i] = 'X'
        print(newlist[i])
        if i < len(newlist) - 2:
            newlist[i+1] = 'A'
            print(newlist[i+1])
        next(islice(numbers, 1, 1), None)

print(newlist)  # debug

结果:

['X', 'X', 'A', 'X', 'A', 'X', 'A']
X
X
X
A
X
A
X
['X', 'X', 'X', 'A', 'X', 'A', 'X']

【讨论】:

    【解决方案5】:

    在混合状态输出和状态更改操作时,您只为每一行显示了列表中的一项。这类似于在没有垂直空白同步的情况下使用超高帧速率。每一行只显示整个图片的一小部分,在这种情况下,A 出现在从其原点向下的每个位置的那一刻。您可以通过打印newlist 而不是newlist[i] 轻松地对此进行可视化。

    移动 A 的操作本身有几个问题。它在一个循环中,我们可以假设它是为了找到 A,但使用 index 方法可以更有效地完成。更重要的是,一旦找到,您将继续循环,因此将继续移动 A 直到它到达末尾 - 在这种情况下,使用 IndexError,因为没有 newlist[i+1] 条目可以交换。确保任务完成一次的传统方法是 break 退出搜索循环。另一种解决方案可能是永远不要更改您正在迭代的列表,而是创建一个从中派生的新一代;那么您将永远不会阅读新修改的职位。

    这里的另一种方法是基于 X 是背景并且所有 As 都向同一方向移动,包括离开列表的末尾:

    newstate = ['X']+oldstate[:-1]    # Shift to higher indices
    

    根据规则表,这是一个只有在可以移动的情况下才会移动的地方:

    moves = {('X', 'A', 'X'): 'X',  # Moved off to the right
             ('A', 'A', 'X'): 'X',  # Moved off to the right
             ('A', 'X', 'X'): 'A',  # Moved in from the left
             ('A', 'X', 'A'): 'A',  # Moved in from the left
            }
    newstate = [moves.get((l,h,r), h) for (l,h,r) in 
                zip(['X']+oldstate, oldstate, oldstate[1:]+['A'])]
    

    这使用 X 作为左边界,A 作为右边界,以避免 As 离开边缘。定义另一个单元状态来表示墙可能很有用。关于这一点,这是一个元胞自动机的例子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-24
      • 2013-07-14
      • 1970-01-01
      • 2013-10-24
      • 1970-01-01
      • 2021-06-10
      • 2021-07-30
      • 2013-03-21
      相关资源
      最近更新 更多