【问题标题】:Efficiently deleting and checking lists有效地删除和检查列表
【发布时间】:2012-07-30 06:35:52
【问题描述】:

现在我正在尝试将战舰棋盘游戏作为练习,并且我大部分时间都在使用带有一些杂项独立功能的类。下面的一切都是独立的。我无法理解它,如果我按列表中从最后一个到第一个的顺序攻击船只,这会起作用,但如果你以任何其他顺序进行,它会破坏说列表索引不存在。请帮忙。

基本上,我的系统是每当一艘船被“击中”(移动与 shipList 中的位置相同)时,它就会添加一个 hitList。这些功能是检查 hitList 中的任何项目是否与船舶的已知位置...在制造船舶对象时在单独的列表中创建。我已经尝试了 2 天来完成这项工作

def checkForSunk(shipList, hitList):

    #Lists is something like this [[0,1],[0,2],[0,3]]
    #ShipList[0] is list, [1] is name of ship
    #ShipList is ALL ships.

    print 'SHIPLIST : %s' % (shipList)
    #[[[[0,1],[0,2],[0,3],[0,4],[0,5],[],[]], 'Destroyer'], [[[0,1],[0,2],[0,3],[0,4],[0,5],[],[]], 'Destroyer'], [[[0,1],[0,2],[0,3],[0,4],[0,5],[],[]], 'Destroyer']]

    #[[[0,1],[0,2],[0,3],[0,4],[0,5],[],[]], 'Destroyer']
    #   0                                       1
    print 'HITLIST : %s ' % (hitList)
    for j in range(len(shipList)):
        for i in shipList[j][0]:
            if i in hitList:
                print 'True in ship # %s' % (shipList[j][1])
                del shipList[j][0][shipList[j][0].index(i)] #Delete that part of the ship from the list.
    #Check if there's any empty ships, and delete the ship if there are.
    for j in range(len(shipList)):
        print shipList[j] #Problem around here!!!!!!!!!!!!
        if listIsEmpty(shipList[j][0]):
            print '%s has been sunk!' % (shipList[j][1])
            del shipList[j]


def isGameOver(shiplist):
    if shiplist == []:
        return True
    else:
        return False

def listIsEmpty(list):
    for i in range(len(list)):
        if list[i] != []: #If it finds anything thats not empty, return False. Else true
            return False
        else:
            return True

我做错了吗?我应该实际删除列表吗?

谢谢

【问题讨论】:

标签: python list for-loop indexing


【解决方案1】:

您遇到的错误已在@gecco 答案中进行了解释。

避免使用嵌套循环可以使代码易于理解。

例如,下面的函数是错误的,因为它只会检查列表中的第一个元素。

def listIsEmpty(list):
    for i in range(len(list)):
        if list[i] != []: #If it finds anything thats not empty, return False. Else true
            return False
        else:
            return True

可以写成

def listIsEmpty(alist):
    return not any(alist)

还有 checkForSunk 函数

#Check if there's any empty ships, and delete the ship if there are.
for j in range(len(shipList)):
    print shipList[j] #Problem around here!!!!!!!!!!!!
    if listIsEmpty(shipList[j][0]):
        print '%s has been sunk!' % (shipList[j][1])
        del shipList[j]

可以写成

# sometimes use filter can make thing easier.
shipList = [k for k in shipList if not listIsEmpty(k[0])]

【讨论】:

    【解决方案2】:

    如果我理解得很好,您的 hitlist 包含所有命中(意思是,您不会在每次移动时检查):如果是这样,则 gecco 的症状是正确的:您不能在迭代列表时删除列表中的元素(使索引无效)。但是颠倒列表并不能解决这个问题,因为如果你从第一艘到最后一艘沉船也会遇到同样的问题。

    如果您不想过多更改代码,请将del shipList[j] 替换为shipList[j][0] = None(您不会删除列表元素,因此迭代仍然有效),然后只需重新定义函数isGameOver

    def isGameOver(shiplist):
        ret = True
        for ship in shiplist:
            if shiplist[0] is not None:
                ret = False
                break
        return ret
    

    【讨论】:

      【解决方案3】:

      答案与问题Delete item in a list using a for-loop 相同:

      向后迭代:

      for j in range(len(shipList) - 1, -1, -1):
      

      【讨论】:

      • 是的,但这会创建一个新列表,而不是循环现有的(性能)——编辑:你是对的:reverse 返回一个迭代器,而不是一个新列表。但是请注意,在他的情况下 j 是一个索引,而不是船舶对象本身......所以reversed 方法在这里并没有真正的帮助-
      • 我认为如果你从头到尾沉没船只,你的情况和以前一样......
      【解决方案4】:

      很抱歉,我无法为您提供解决方案代码,因为您没有提供足够的信息或代码供我为您修复。但我提供的代码示例可能有助于您理解这些列表。

      #a list with 10 object
      mylist = [1,2,3,4,5,6,7,8,9,10]
      print mylist
      >>> 
      [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      #if i print the 6th object:
      print mylist[5]
      >>> 
      6
      #if i delete an object from the end:
      del mylist[9]
      print mylist
      >>>
      [1, 2, 3, 4, 5, 6, 7, 8, 9]
      #as you can see, the item is gone, and the list only has 9 objects.
      
      #if i print the 6th object:
      print mylist[5]
      >>> 
      6
      
      #but if i delete an item from the middle
      del mylist[4]
      print mylist
      >>>
      [1, 2, 3, 4, 6, 7, 8, 9]
      #i now have 8 objects as expected, but the objects location in the list has changed.
      
      #if i print the 6th object:
      print mylist[5]
      >>> 
      7
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 2021-11-01
        • 2021-10-13
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        • 1970-01-01
        • 2010-10-30
        • 2015-01-17
        • 2020-02-05
        相关资源
        最近更新 更多