Удаление элементов из вложенного списка Python - PullRequest
7 голосов
/ 24 марта 2012

Я пытаюсь удалить элементы из вложенного списка в Python.У меня есть следующий вложенный список:

families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]]

Я хочу удалить записи в каждом подсписке, которые соответствуют индексированной позиции подсписка в основном списке.Так, например, мне нужно удалить 0 из первого подсписка, 1 из второго подсписка и т. Д. Я пытаюсь использовать понимание списка, сделайте это.Это то, что я пробовал:

familiesNew = [ [ families[i][j] for j in families[i] if i !=j ] for i in range(len(families)) ] 

Это работает для range(len(families)) до 3, однако после этого я получаю IndexError: list index out of range.Я не уверен почему.Может кто-нибудь дать мне представление о том, как это сделать.Предпочтительно однострочник (понимание списка).

Спасибо.

Ответы [ 4 ]

9 голосов
/ 24 марта 2012

Вы почти правильно поняли.Просто замените families[i][j] на j, и это сработает:

>>> [ [ j for j in families[i] if i !=j ] for i in range(len(families)) ]
[[1, 2], [0, 2, 3], [0, 1, 3, 4], [1, 2, 4, 5], [2, 3, 5, 6]]

Его можно написать немного чище, используя функцию enumerate:

>>> [[f for f in family if f != i] for i, family in enumerate(families)]
[[1, 2], [0, 2, 3], [0, 1, 3, 4], [1, 2, 4, 5], [2, 3, 5, 6]]

Или даже используя remove если вы не возражаете против изменения исходного списка:

>>> for i, family in enumerate(families): family.remove(i)
5 голосов
/ 24 марта 2012

Отредактированный вопрос, удаляя мой ответ, который решал не ту проблему. Также добавлен дополнительный ответ @Ashwini:

Для сравнения:

root# python -m timeit 'families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]]' '[x.remove(ind) for ind,x in enumerate(families) ]'
100000 loops, best of 3: 3.42 usec per loop    

root# python -m timeit -s 'families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]]' '[[f for f in family if f != i] for i, family in enumerate(families)]'
100000 loops, best of 3: 4.87 usec per loop

root# python -m timeit -s 'families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]]' '[ filter(lambda x:x!=i,j) for i,j in enumerate(families) ]'
100000 loops, best of 3: 7.99 usec per loop

Это микросекунды, так что я думаю, что все, что вы хотите сделать, хорошо, если вы не собираетесь делать это лот раз.

3 голосов
/ 24 марта 2012

Делает ли это то, что вы хотите?

familiesNew=[ filter(lambda x:x!=i,j) for i,j in enumerate(families) ]

EDIT

Также обратите внимание, что ваша ошибка не состояла в том, что в третьем элементе внешнего списка ([1, 2, 3, 4, 5]) вы пытаетесь получить пятый элемент в цикле for (for j in families[i] == for j in [1,2,3,4,5]), но family [i] имеет длину 5, что означает, что самый большой индекс равен 4. Извините, если это объяснение немного неясно ... возможно, следующее поможет немного прояснить это:

families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]]

def f(i,j):
    print i,j,families[i]
    return families[i][j]
#THIS DOES NOT WORK -- but it will tell you where it failed.
familiesNew = [ [ f(i,j) for j in families[i] if i !=j ] for i in range(len(families)) ] 
2 голосов
/ 24 марта 2012

Если вы хотите изменить исходный список, попробуйте следующее:

>>>[x.remove(ind) for ind,x in enumerate(families) ]
>>>families
[[1, 2], [0, 2, 3], [0, 1, 3, 4], [1, 2, 4, 5], [2, 3, 5, 6]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...