尝试删除list [i] [0]和list [i] [1] == 0的列表中的行时抛出“list out of range”

时间:2016-11-28 23:15:03

标签: python nested-lists

我正在尝试删除数组中前两列有0值的行。我的代码是:

  for i in range (5680):
        if games[i][0] == 0 and games[i][1] == 0:                   
            games.pop(i)
  print(games)

在第二行下面放置games[i][0]games[i][1]的打印语句会打印出一大堆0行,所以我知道这些行确实存在。我是即使游戏是list out of range5680矩阵,也会出现5错误。 无论我尝试什么,仍然会抛出更改错误。怎么回事?

4 个答案:

答案 0 :(得分:1)

如果您要从games删除行(与games.pop(i)一样),它将不再有5680行,因此只要删除至少1行,最终尝试访问games[5679],这会让您列出超出范围'因为你不再拥有那么多行。

答案 1 :(得分:1)

一旦调用games.pop(i)games矩阵的维度就会从5680x5变为5679x5,并随着每次连续调用而减小。与此同时,for i in range(5680)不断迭代[0, ..., 5680],这意味着稍后某些i肯定会超出范围。

有很多方法可以防止这种情况发生。一种简单的方法是以相反的顺序检查games的索引。这样,如果弹出索引game_index,迭代中的下一个索引game_index - 1仍将存在于矩阵中。

# iterate in reverse order
for i in range(5680, 0, -1):
    game_index = i-1
    if games[game_index][0] == 0 and games[game_index][1] == 0:
        games.pop(game_index)

print(games)

如果您希望仅弹出一些项目,则此过程通常很好。如果您希望弹出大多数项目,那么创建新列表可能会更高效。

games = [game for game in games if game[0] != 0 and game[1] != 0]

答案 2 :(得分:1)

尝试更改正在迭代的对象几乎总是一个坏主意。在你的情况下,在第一个pop()之后,你的列表已经小于5680.所以当你到达5679时,你已经超出了范围。

试试这个:

games = [g for g in games if g[0] != 0 or g[1] != 0]

games = list(filter(lambda g: g[0] != 0 or g[1] !=0, games))

答案 3 :(得分:0)

您在迭代时改变列表。 这失败了。弹出第一个项目后,列表中不再有5680个元素,因此您无法访问这些元素。

而是使用过滤器操作生成新列表。

new_games = filter(lambda row: row[0] != 0 or row[1] != 0, games)

Handy examples