Python"不在"索引超出范围

时间:2015-12-23 18:26:27

标签: python indexoutofrangeexception

我正在处理某种问题,我找不到任何解决方案。 我的问题是我在嵌套列表中控制一个值,如果它不在另一个列表中,如果它不在那里则删除它但在不在行中它会给我一个像索引超出范围的错误。

def heroes_updater(men_pref,women):
   for i in range(0,len(men_pref)-1):
      for j in range(0,len(men_pref[i])-1):
          if men_pref[i][j] not in women:
              men_pref[i]=men_pref[i][:j]+men_pref[i][j+1:]

示例men_pref:

[['Storm', 'Black Widow', 'Scarlet Witch', 'Rouge', 'Mystique', 'Jean Grey', 'Ms. Marvel', 'Gamora', 'Invisible Woman', 'Elektra'], ['Storm', 'Elektra', 'Jean Grey', 'Scarlet Witch', 'Mystique', 'Ms. Marvel', 'Gamora', 'Rouge', 'Black Widow', 'Invisible Woman'], ['Invisible Woman', 'Scarlet Witch', 'Mystique', 'Black Widow', 'Ms. Marvel', 'Elektra', 'Jean Grey', 'Gamora', 'Storm', 'Rouge']]

示例女性:

['Jean Grey', 'Elektra', 'Mystique', 'Ms. Marvel', 'Rouge']

错误是:

if men_pref[i][j] not in women:
  

IndexError:列表索引超出范围

3 个答案:

答案 0 :(得分:1)

您正在编辑您正在阅读的列表,您绝不能这样做。

使用第men_pref[i]=men_pref[i][:j]+men_pref[i][j+1:]行 您正在从列表men_pref[i]中删除某个项目,但您的j变量从0变为列表的原始长度,因此您最终会有一个索引如果men_pref[i][j]

,则检查j>len(men_pref[i])时出错

编辑: 当然,如果您想要编辑当前列表,那么您必须使用向后索引读取它(从最后开始,如果它不在女性列表中,则将其删除然后继续下一个项目):

def heroes_updater(men_pref,women):
    for i in range(len(men_pref)-1, -1,-1):
        for j in range(len(men_pref[i])-1, -1, -1):
            if men_pref[i][j] not in women:
                men_pref[i].pop(j)
                # An alternative: del(mem_pref[i][j])

另一种方法是使用列表理解:

def heroes_updater(men_pref,women):
    for i in range(len(men_pref)-1, -1,-1):
        mem_pref[i] = [_w_ for _w_ in mem_pref[i] if _w_ in women]

还有其他选择,但我会留给你。 这就是你学习的方式。

答案 1 :(得分:1)

通过从列表中删除元素,列表变得更短j大于列表的长度。为了避免这个问题,不要改变列表,而是创建一个新列表:

def heroes_updater(men_pref,women):
   result = []
   for prefs in men_pref:
      new_prefs = []
      for pref in prefs:
          if pref in women:
              new_prefs.append(pref)
      result.append(new_prefs)
   men_pref[:] = result

或更好:

def filter_non_heroes(men_pref,women):
    return [
        [pref for pref in prefs if pref in women]
        for prefs in men_pref
    ]

答案 2 :(得分:1)

您可以使用带有列表组合的集合,您不能迭代并改变列表,因为每次删除元素时列表变小,并且您的索引基于启动范围时列表的大小:

men = [['Storm', 'Black Widow', 'Scarlet Witch', 'Rouge', 'Mystique', 'Jean Grey', 'Ms. Marvel', 'Gamora', 'Invisible Woman', 'Elektra'], ['Storm', 'Elektra', 'Jean Grey', 'Scarlet Witch', 'Mystique', 'Ms. Marvel', 'Gamora', 'Rouge', 'Black Widow', 'Invisible Woman'], ['Invisible Woman', 'Scarlet Witch', 'Mystique', 'Black Widow', 'Ms. Marvel', 'Elektra', 'Jean Grey', 'Gamora', 'Storm', 'Rouge']]

wom = {'Jean Grey', 'Elektra', 'Mystique', 'Ms. Marvel', 'Rouge'}

men[:] = [[ele for ele in sub if ele in wom] for sub in men]

print(men)

或在功能上如果订单无关紧要:

men = [['Storm', 'Black Widow', 'Scarlet Witch', 'Rouge', 'Mystique', 'Jean Grey', 'Ms. Marvel', 'Gamora', 'Invisible Woman', 'Elektra'], ['Storm', 'Elektra', 'Jean Grey', 'Scarlet Witch', 'Mystique', 'Ms. Marvel', 'Gamora', 'Rouge', 'Black Widow', 'Invisible Woman'], ['Invisible Woman', 'Scarlet Witch', 'Mystique', 'Black Widow', 'Ms. Marvel', 'Elektra', 'Jean Grey', 'Gamora', 'Storm', 'Rouge']]

wom = {'Jean Grey', 'Elektra', 'Mystique', 'Ms. Marvel', 'Rouge'}

men[:] = map(list,map(wom.intersection, men))

print(men)

您也可以从列表末尾开始,使用范围逻辑但使用range(len(sub)-1,-1, -1),但更容易使用反转并迭代元素本身:

def heroes_updater(men_pref, women):
    for sub in men_pref:
        for m in reversed(sub):
            if m not in women:
                sub.remove(m)