2014-01-30 5 views
0

Я пытаюсь удалить кортеж из списка. Если первый элемент в списке равен «-NONE-», я хочу удалить весь кортеж. Я продолжаю ошибаться, когда я пробую разные вещи. Вот что у меня есть:Удаление кортежей из списка

def filter(sent): 
    for tuple in sent: 
     if tuple[1] == "-NONE-": 
      sent.remove(sent.index(tuple)) 

Я использую этот тест, чтобы вызвать метод:

filter([('uh', 'UH'), ('i', 'PRP'), ('think', 'VBP'), (',', ','), ('*0*', '-NONE-'), ('it', 'PRP'), ("'s", 'BES'), ('because', 'IN'), ('i', 'PRP'), ('get', 'VBP'), ('*', '-NONE-'), ('to', 'TO'), ('be', 'VB'), ('something', 'NN'), ('that', 'WDT'), ('i', 'PRP'), ("'m", 'VBP'), ('not', 'RB'), ('*T*', '-NONE-'), ('.', '.')]) 

, но я получаю эту ошибку:

Traceback (most recent call last): 
File "<pyshell#273>", line 1, in <module> 
filter([('uh', 'UH'), ('i', 'PRP'), ('think', 'VBP'), (',', ','), ('*0*', '-NONE-'), ('it', 'PRP'), ("'s", 'BES'), ('because', 'IN'), ('i', 'PRP'), ('get', 'VBP'), ('*', '-NONE-'), ('to', 'TO'), ('be', 'VB'), ('something', 'NN'), ('that', 'WDT'), ('i', 'PRP'), ("'m", 'VBP'), ('not', 'RB'), ('*T*', '-NONE-'), ('.', '.')]) 
File "<pyshell#272>", line 4, in filter 
    sent.remove(sent.index(tuple)) 
ValueError: list.remove(x): x not in list 

ответ

1

Все, что вам нужно сделать, это

sent.remove(tuple) 

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

sent.pop(sent.index(tuple)) 

Remove находит объект в списке, а затем удаляет его (но только если она есть). Поп работает с индексами


Как user2357112 отметил, вы не должны извлекать элементы из того же списка вы итерацию над. Это, несомненно, вызовет у вас головную боль. Их ответ лучше.

5

Метод remove принимает объект для удаления из списка, а не индекс. Вы можете использовать либо del, который действительно принимает индекс, или передать кортеж remove непосредственно:

def filter(sent): 
    for tuple in sent: 
     if tuple[1] == "-NONE-": 
      # del sent[sent.index(tuple)] 
      sent.remove(tuple) 

Однако, это еще не будет работать. Вы изменяете список, итерации по нему, что приведет к потере вашей позиции на итерации. Кроме того, и index, и remove являются медленными, и это плохая идея назвать функцию filter, скрывая встроенную функцию filter. Это, скорее всего, будет лучше создать новый, отфильтрованный список со списком понимания:

def filtered(sent): 
    return [item for item in sent if item[1] != "-NONE-"] 
+0

Хорошо поймать. Я не заметил, что он удалял предметы из того же списка, что и итерации. –

0

Ваша непосредственная ошибка в том, что list.remove ожидает элемент в качестве аргумента, а не индекс. То есть, вы хотите использовать sent.remove(tuple), а не sent.remove(sent.index(tuple)). Или, наоборот, используйте del, который удаляет по индексу (del sent[sent.index(tuple)]). Однако при любом из этих исправлений у вас все еще будут проблемы с вашим алгоритмом.

Причина в том, что вы повторяете список в то же время, когда вы удаляете элементы из него. Перечисляет итерацию, используя индексы внутри, поэтому, когда вы удаляете один элемент, все последующие перемещаются на одно место, а следующий элемент после того, который вы удалили, будет пропущен итерацией.

Лучший подход, как правило, использовать список понимание для фильтрации списка:

def filter(sent): 
    return [tuple for tuple in sent if tuple[1] != "-NONE-"] 

Обратите внимание, что это возвращает новый список, а не модифицируя исходный список на месте. Если вы хотите изменить ситуацию на месте, вы можете это сделать, но вам нужно будет перебирать список в обратном порядке, чтобы индексы значений, которые вы еще не проверили, не будут изменены.Вот один из возможных способов сделать это, хотя они все немного некрасиво:

def filter(sent): 
    for i, val in enumerate(reversed(sent), 1): # iterate in reverse order 
     if val[1] == "-NONE-": 
      del sent[-i] # del operator removes items by index 
0

Вместо определения своей собственной функции фильтра, используйте встроенный функции:

z = [('uh', 'UH'), ('i', 'PRP'), ('think', 'VBP'), (',', ','), ('*0*', '-NONE-'), ('it', 'PRP'), ("'s", 'BES'), ('because', 'IN'), ('i', 'PRP'), ('get', 'VBP'), ('*', '-NONE-'), ('to', 'TO'), ('be', 'VB'), ('something', 'NN'), ('that', 'WDT'), ('i', 'PRP'), ("'m", 'VBP'), ('not', 'RB'), ('*T*', '-NONE-'), ('.', '.')] 
z_filtered = filter(lambda item: item[1] != '-NONE-', z) 

Или используйте itertools.ifilter():

import itertools as it 
filtered = list(it.ifilter(lambda item: item[1] != '-NONE-', z)) 

Те оба немного медленнее, чем @ Blckknght-й или @ user2357112 в списке понимание. Это конкурентное преимущество:

def f(z): 
    for item in z: 
     if item[1] != '-NONE-': 
      yield item 
filtered = list(f(z)) 
Смежные вопросы