[英]Removing tuples from a list
我正在尝试从列表中删除一个元组。 如果列表中的第一个元素等于“ -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
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-"]
您需要做的就是
sent.remove(tuple)
如果您绝对想找到索引,则需要使用pop
,如下所示:
sent.pop(sent.index(tuple))
Remove在列表中找到该对象,然后将其删除(但前提是该对象存在)。 带有索引的流行作品
如user2357112所述,您不应该从迭代的同一列表中删除项目。 这无疑会引起您的头痛。 他们的答案是更好的答案。
您的直接错误是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
不用定义自己的过滤器函数,而使用内置函数:
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))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.