在python中从2D列表中获取特定元素时遇到问题

在python中从2D列表中获取特定元素时遇到问题,python,excel,multidimensional-array,indexoutofboundsexception,Python,Excel,Multidimensional Array,Indexoutofboundsexception,因此,我试图删除一个二维数组中的所有元素,该数组是从一个excel工作表中获取的,带有几个标题中的一个。值是包含我的数据的二维数组。我的主要问题之一是,并非所有行的最后一列中都有需要删除的内容,这会导致大量索引越界错误。注意,二维数组的第一个维度是行 badColumns = ['Queue', 'Subject', 'Risk', etc...] #Some other ones are here for col in range(len(values[0])): for badTe

因此,我试图删除一个二维数组中的所有元素,该数组是从一个excel工作表中获取的,带有几个标题中的一个。值是包含我的数据的二维数组。我的主要问题之一是,并非所有行的最后一列中都有需要删除的内容,这会导致大量索引越界错误。注意,二维数组的第一个维度是行

badColumns = ['Queue', 'Subject', 'Risk', etc...] #Some other ones are here

for col in range(len(values[0])):
    for badText in badColumns:
        if badText in values[0][col]:
            for row in range(len(values)):
                try:
                    del values[row][col]
                except IndexError:
                    continue

在del语句周围抛出print语句不会显示del语句的任何更改。知道这是什么原因吗?提前感谢您的帮助。

看起来您正在修改列表,这会导致出现问题。根据你分享的内容,这并不能解释你所有的问题,但应该会有所帮助

运行此代码作为您遇到问题的示例;如果这不能清楚地说明问题,我很乐意提供更多帮助:

#Bad Code:

a = range(6)
print a
for i in range(len(a)):
    try:
        del a[i]
    except IndexError:
        print 'Bad index', i
print a
输出:

[0, 1, 2, 3, 4, 5]
Bad index 3
Bad index 4
Bad index 5
[1, 3, 5]
[0, 1, 2, 3, 4, 5]
[]
这段代码更好:(嗯,也许吧?不太像Python,但它能工作…)

输出:

[0, 1, 2, 3, 4, 5]
Bad index 3
Bad index 4
Bad index 5
[1, 3, 5]
[0, 1, 2, 3, 4, 5]
[]
下面是坏代码中发生的情况:

首先,a=[0,1,2,3,4,5]

那么,i=0

现在a[i]被删除,因此a=[1,2,3,4,5]

那么,i=1

现在a[i]被删除,因此索引1处的元素被删除,而不是索引0


因此,现在a=[1,3,4,5],您已经跳过了删除元素“1”

您的代码有两个问题

首先,不能在遍历序列时对其进行修改*

第二,如果在序列中间插入或删除,则会改变所有以下索引。

可以用两种方法解决第一个问题:在迭代副本时修改序列,或者在迭代原始副本时构建新副本

如果使用前一种(变异)解决方案,通常可以通过向后迭代副本来解决第二个问题。如果您正在删除或插入的索引与您正在迭代的索引相同,那么这保证是安全的,因为它只会触及您已经迭代过的后面的索引

如果使用后一种解决方案,它会自动解决第二个问题


作为旁注,在Python中迭代序列的最简单方法是直接进行迭代,而不是构建
范围(len())
,然后建立索引。如果您还需要索引,可以使用
enumerate
获得它


不管怎么说,您似乎要做的是删除其标题值包含任何badColumns名称的任何列,对吗?让我们将其重写为一个非变异函数,它构建一个没有这些列的新表

def isBadColumn(text):
    for badText in badColumns:
        if badText in text:
            return True

badIndices = set()
for idx, header in enumerate(values[0]):
    if isBadColumn(header):
        badIndices(idx)

newValues = []
for row in values:
    newRow = []
    for idx, col in enumerate(row):
        if idx not in badIndices:
            newRow.append(col)
    newValues.append(newRow)

values = newValues

但是所有这些显式的
for
循环都可以很容易地转化为理解,因此整个过程归结为:

badIndices = {idx for idx, header in enumerate(values[0])
              if any(badText in header for badText in badColumns)}
values = [[col for idx, col in row if idx not in badIndices] for row in values]

如果您需要通过适当地改变
来执行此操作(例如,因为某些其他代码引用了
,并且必须看到它发生了变化),这里有一个等价的:

# all of the code to get badIndices from above

for rowidx, row in reversed(enumerate(values)):
    for colidx, col in reversed(enumerate(row)):
        if colidx in badIndices:
            del values[rowidx][colidx]

同时,您可能首先需要考虑不同的数据结构。例如,如果您将每一行存储为

dict
(或
orderedict
,如果您需要保留列顺序)而不是
列表,则可以执行以下操作:

badHeaders = {header for header in values[0]
              if any(badText in header for badText in badColumns)}
然后生成一个新副本:

values = [{header: value for header, value in row.items() 
           if header not in badColumns}
          for row in values]
或就地突变:

for row in values:
    for header in badHeaders:
        del row[header]


*这并不完全正确,您可以替换单个值,并用等长切片替换切片。但是您不能插入或删除元素,也不能用不同大小的切片替换切片,并且您正在尝试删除。

为什么不确定要删除哪些列呢?这似乎是IndexOutofBounds的来源,但您仍在尝试在遍历它时找到修改的方法。我怎么能不这样做呢?我现在没有想出任何好的解决办法。。。尝试在原始代码中使用
[::-1]
,看看它是否正确helps@avorum删除或插入序列中间会改变所有以下索引,这意味着您将跳过或重复其中一个元素。解决方法是向后迭代序列,如答案所示。同时,您不能在遍历序列时实际修改它;您必须在遍历序列副本时修改原始副本,或者在遍历原始副本时构建副本(后者通常更具Pythonic)。我无法决定是建议您创建副本(更具Pythonic)还是仅删除元素(更高效)。。。我可以告诉你,为了进行调试,你应该用某种打印语句替换
continue
。你知道关于理解的好教程吗?我经常看到它们,语法对我来说毫无意义。@avorum:我不知道有什么比官方教程中的内容更好的了,所以如果没有帮助的话……我很快就写了一些东西;如果有帮助,请告诉我。