从列表中删除元组

时间:2014-01-30 03:27:09

标签: python 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

4 个答案:

答案 0 :(得分:5)

remove方法从列表中删除对象,而不是索引。你可以使用del,它确实取一个索引,或直接将元组传递给remove

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

然而,这仍然行不通。你在迭代它时修改列表,这会搞砸你在迭代中的位置。此外,indexremove都很慢,命名函数filter是一个坏主意,隐藏了内置的filter函数。使用列表推导创建一个新的过滤列表最有可能更好:

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

答案 1 :(得分:1)

您需要做的就是

sent.remove(tuple)

如果您绝对想要找到索引,则需要使用pop,例如:

sent.pop(sent.index(tuple))

删除查找列表中的对象,然后将其删除(但只有在那里)。 Pop使用索引


正如user2357112所指出的那样,您不应该从迭代的同一列表中删除项目。这无疑会让你头疼。他们的回答是更好的。

答案 2 :(得分: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

答案 3 :(得分: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))