2015-12-23 2 views
3

Я имею дело с какой-то проблемой, и я не смог найти решение. Моя проблема заключается в том, что я контролирую значение во вложенном списке, если он не находится в другом списке и удаляет его, если его нет, но в не в строке он дает мне ошибку, такую ​​как индекс за пределами диапазона.Python "not in" index out of range enrror

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: list index out of range

+0

является его что вы пропустите последний или последний два элемента? – Daniel

+0

Что вы на самом деле пытаетесь достичь? –

+0

нет, я просто пытался что-то и, как я знаю, -1 должен быть там, потому что функция len() дает информацию о том, сколько элементов есть, и я имею дело с индексами, которые на 1 меньше. Я обновил -2 как -1 – ogzgl

ответ

2

Удаляя элементы из вашего списка, список становится короче. 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 
    ] 
+0

Спасибо. Он работает очень хорошо, и, поскольку я понимаю проблему, ваше решение имеет большой смысл. – ogzgl

2

Вы редактировать в списке, который вы читаете, вы никогда не должны этого делать.

С линией 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])

EDIT: из, если вы хотите изменить ваш текущий список, то вы должны будете читать его с обратной индекса (вы начинаете с последнего, если это не входит в список женщин, удалить а затем продолжить со следующего пункта):

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] 

Есть и другие варианты, но я оставлю это для вас. Вот как вы учитесь.

+0

Хорошо. Я это понимаю. Это дает ошибку, потому что ее длина и индексы, конечно, меняются. – ogzgl

+0

«Вы никогда не должны этого делать» - вы можете легко это сделать, если поймете, что происходит. Но в этом случае вы совершенно правы, это лишь добавляет путаницы. – kindall

+0

Спасибо за решения, так как я знаю, в чем причина ошибки. Я могу справиться с этим. Спасибо. – ogzgl

2

Вы можете использовать набор со списком компе, вы не можете перебирать и мутировать список, как каждый раз, когда вы удалите элемент списка становится все меньше и ваш индекс основан на том, что размер списка, когда вы начали диапазон:

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) 
+0

Спасибо, я понял проблему – ogzgl

+0

@ulmotl, не беспокойтесь, вы также можете использовать почитание или начать свой диапазон в конце каждого списка, список comp с набором является наиболее эффективным, хотя –