繁体   English   中英

从列表中删除元组

[英]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)

但是,这仍然行不通。 您在迭代列表的同时对其进行了修改,这将增加您在迭代中的位置。 同样, indexremove都很慢,并且命名一个函数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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM