【问题标题】:Looping over list of lists (nested for-loops) doesnt work as I want it to循环列表列表(嵌套的for循环)不能按我的意愿工作
【发布时间】:2014-05-14 18:58:06
【问题描述】:

我想要做的是遍历 board 中的元素,寻找“P”,然后检查是否有 5 个“P”连续(向下,可以这么说)。请参阅代码中的 cmets 以获得进一步的解释。尽管如此,inRow 仍然给我输出 15。

提示:五个“P”不应该是静止的,而是由玩家放置的,但在这个例子中,我只是放置了静止的。

board = [['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E']]
# has 10 rows, with 10 elements in each

inRow=0

for y in range(10): # Loops over each row (y-index)
    x=0 # x-index resets each new y-index loop (start on the first element (0) of each row)
    for pos in board[y]: # pos loops over all elements in current row 
        if pos is "P": # checks if pos is "P"
            for i in range(5): # loops over 0, 1, 2, 3, 4
                if board[y+i][x] is "P": # when i=0, board[y+i][x] is ought to be where we find the first "P", then check if the following rows (we add +1 to y for each loop) is also "P"
                    inRow += 1 # Counter to see if we got 5 in a row
            break 
        x+=1

print(inRow)

【问题讨论】:

  • 作者希望inRow5,但得到了15
  • 不要将is 与字符串一起使用。 is 测试相同的对象,而不是相等的字符串。
  • 您需要在嵌套循环中制作它吗?如果是这样,建议首先循环遍历列,然后遍历行。
  • @Daniel 好的!那么,改用 == 吗?

标签: python for-loop nested-loops


【解决方案1】:

即使没有连续的5“P”,您也可以添加到inRow。想一想:

当您第一次在第二行点击“P”时,您会倒计时并获得5。下次您在外部for 循环中点击“P”时,您倒计时并得到4。现在你已经数完了9“P”。继续这个,你会得到5 + 4 + 3 + 2 + 1 = 15"P"s。

解决方案是使用中间计数器,如果该计数器为5,则仅将该中间计数添加到inRow

要正确计数,你可以在for pos in board[y]:之后声明一个计数器

counter = 0

然后,您可以使用counter += 1,而不是inRow += 1

最后,在你的 break 语句之前,做一个检查:

if counter == 5:
    inRow += counter

【讨论】:

  • 这非常适合如果您有超过 5 个“P”并搜索所有 5-in-a-rows。但是,我一次只能有 5 个“P”(我应该提到它,对不起!)因此另一个帖子被标记为答案。
【解决方案2】:

问题是当你中断时,你并没有结束两个循环——只有第二个循环。

因此,当您的代码找到第一个 P 时,它会递增 inRow 直到等于 5,然后中断。然后你的代码移动到第二行,到第二个P,并递增inRow,直到等于9——5 + 4 = 9

虽然您可以重构代码来完全避免这个问题,但您也可以将代码包装在一个函数中,然后简单地返回而不是中断:

board = [['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'P', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'],
        ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E']]

def find(board):
    inRow=0
    for y in range(10): 
        x = 0 
        for pos in board[y]: 
            if pos == "P": 
                for i in range(5): 
                    if board[y+i][x] == "P": 
                        inRow += 1 
                return inRow 
            x += 1
    return inRow

print(find(board))

【讨论】:

  • 我不认为这是完全正确的,尽管它可以为作者提供针对他们遇到的特定问题的正确输出。如果将第二组“P”放在第一组的右侧,则输出将是 5,而不是预期的 10
  • 虽然我没有使用你的建议解决它(因为我这样做的方式在整个项目中使用时更合适(而不仅仅是我在这里粘贴的小例子))你帮助了我了解出了什么问题(“不破坏第一个 for 循环”部分)非常感谢!
【解决方案3】:

如果行中没有 5 个“P”,则必须设置 Flag,然后检查 flag 是否为真,然后增加 inRow

inRow=0

for y in range(10):
    x=0 
    for pos in board[y]:
        if pos is "P": 
            flag=True

            for i in range(5): 
                if  not board[y+i][x] is "P":
                    flag=False
            if flag:
                inRow+=1
            break 
        x+=1

print(inRow)

【讨论】:

  • 这将返回1。作者期望5
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-22
  • 2020-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多