python 如何删除列表中存在的项目?

t30tvxxf  于 2022-12-10  发布在  Python
关注(0)|答案(9)|浏览(159)

我从表单文本字段self.response.get("new_tag")获取new_tag,从复选框字段selected_tags获取selected_tags

self.response.get_all("selected_tags")

我把它们组合成这样:

tag_string = new_tag
new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)

f1.striplist是一个函数,用于去除列表中字符串内白色。)
但是在tag_list为空(没有输入新标签)但存在一些selected_tags的情况下,new_tag_list包含空字符串" "
例如,从logging.info

new_tag
selected_tags[u'Hello', u'Cool', u'Glam']
new_tag_list[u'', u'Hello', u'Cool', u'Glam']

如何去掉空字符串?
如果列表中有空字符串:

>>> s = [u'', u'Hello', u'Cool', u'Glam']
>>> i = s.index("")
>>> del s[i]
>>> s
[u'Hello', u'Cool', u'Glam']

但如果没有空字符串:

>>> s = [u'Hello', u'Cool', u'Glam']
>>> if s.index(""):
        i = s.index("")
        del s[i]
    else:
        print "new_tag_list has no empty string"

但这给出:

Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    if new_tag_list.index(""):
        ValueError: list.index(x): x not in list

为什么会发生这种情况,我该如何解决它?

2ekbmq32

2ekbmq321#

1)近乎英式风格:

使用in运算子测试是否存在,然后套用remove方法。

if thing in some_list: some_list.remove(thing)

remove方法只会移除第一个出现的thing,若要移除所有出现的while,您可以使用while来取代if

while thing in some_list: some_list.remove(thing)
  • 足够简单,可能是我的选择。对于小列表(无法抗拒一行程序)

2)鸭子型,EAFP型:

这种“先问问题,后解决问题”的态度在Python中很常见,我们不需要事先测试对象是否合适,只需执行操作并捕获相关的异常即可:

try:
    some_list.remove(thing)
except ValueError:
    pass # or scream: thing not in some_list!
except AttributeError:
    call_security("some_list not quacking like a list!")

当然,上面例子中的第二个except子句不仅幽默感可疑,而且完全没有必要(重点是为不熟悉这个概念的人演示duck-typing)。
如果您预期某件事会多次发生:

while True:
    try:
        some_list.remove(thing)
    except ValueError:
        break
  • 对于这个特定用例来说有点冗长,但是在Python中非常符合习惯。
  • 这比#1表现更好
  • PEP 463为try/except的简单用法提出了一个较短的语法,在这里会很方便,但没有得到批准。

然而,使用contextlib的suppress()contextmanager(在python 3.4中引入),上面的代码可以简化为:

with suppress(ValueError, AttributeError):
    some_list.remove(thing)

同样,如果您预期某件事会多次发生:

with suppress(ValueError):
    while True:
        some_list.remove(thing)

3)功能风格:

大约在1993年,Python得到了lambdareduce()filter()map(),这是一个Lisp黑客的好意,他错过了它们并提交了工作补丁 *。

is_not_thing = lambda x: x is not thing
cleaned_list = filter(is_not_thing, some_list)

有一个可能对您的情况有用的快捷方式:如果你想过滤掉空项(实际上是bool(item) == False,比如None,零,空字符串或其他空集合),你可以传递None作为第一个参数:

cleaned_list = filter(None, some_list)

*【更新】:在Python 2.x中,filter(function, iterable)曾经等价于[item for item in iterable if function(item)](如果第一个参数是None,则等价于[item for item in iterable if item]);在Python 3.x中,它现在等价于(item for item in iterable if function(item))。细微的区别在于,filter用于返回一个列表,现在它像一个生成器表达式一样工作--如果你只是迭代清理过的列表并丢弃它,这是可以的,但是如果你真的需要一个列表,你必须用list()构造函数来封装filter()调用。

4)数学样式:

自从PEP 202在Python 2.0版本中引入以来,List comprehensions就成为列表操作的首选样式。其背后的基本原理是,在当前使用map()filter()和/或嵌套循环的情况下,List解析提供了一种更简洁的方法来创建列表。

cleaned_list = [ x for x in some_list if x is not thing ]

生成器表达式是由PEP 289在2.4版本中引入的。生成器表达式更适合于不需要在内存中创建完整列表的情况--比如只想一次迭代一个元素的情况。如果只迭代列表,可以将生成器表达式视为lazy evaluated列表解析:

for item in (x for x in some_list if x is not thing):
    do_your_thing_with(item)

备注

1.您可能希望使用不等运算符!=而不是is notthe difference is important
1.对于暗示列表复制的方法的批评者:与普遍的看法相反,生成器表达式并不总是比列表解析更有效--请在抱怨之前进行分析

arknldoa

arknldoa2#

try:
    s.remove("")
except ValueError:
    print "new_tag_list has no empty string"

请注意,这只会从列表中删除一个空字符串示例(代码也会这样做)。您的列表可以包含多个空字符串示例吗?

rfbsl7qr

rfbsl7qr3#

作为一个班轮公司:

>>> s = [u'', u'Hello', u'Cool', u'Glam']
>>> s.remove('') if '' in s else None # Does nothing if '' not in s
>>> s
['Hello', 'Cool', 'Glam']
>>>
rqenqsqc

rqenqsqc4#

如果index没有找到要搜索的字符串,它将抛出您看到的ValueError

try:
    i = s.index("")
    del s[i]
except ValueError:
    print "new_tag_list has no empty string"

使用find,在这种情况下会传回-1。

i = s.find("")
if i >= 0:
    del s[i]
else:
    print "new_tag_list has no empty string"
gg0vcinb

gg0vcinb5#

添加此答案是为了完整性,尽管它仅在特定条件下可用。
如果你有非常大的列表,从列表末尾删除可以避免CPython内部必须执行memmove,因为你可以重新排序列表。从列表末尾删除可以提高性能,因为它不需要在你删除的项之后执行memmoveevery item- back one step(1)。
对于一次性删除,性能差异可能是可以接受的,但如果列表很大,需要删除许多项,则可能会出现性能下降。
当然,在这些情况下,进行全列表搜索也可能是一个性能瓶颈,除非项目大部分位于列表的前面。
该方法可用于更有效的去除,
只要重新排序列表是可接受的。(2)

def remove_unordered(ls, item):
    i = ls.index(item)
    ls[-1], ls[i] = ls[i], ls[-1]
    ls.pop()

item不在列表中时,您可能希望避免引发错误。

def remove_unordered_test(ls, item):
    try:
        i = ls.index(item)
    except ValueError:
        return False
    ls[-1], ls[i] = ls[i], ls[-1]
    ls.pop()
    return True

1.虽然我用CPython测试了这一点,但很可能大多数/所有其他Python实现都使用数组在内部存储列表。因此,除非它们使用一种为高效调整列表大小而设计的复杂数据结构,否则它们很可能具有相同的性能特征。
一个简单的测试方法是比较从列表的前面删除与删除最后一个元素的速度差异:

python -m timeit 'a = [0] * 100000' 'while a: a.remove(0)'

具有:

python -m timeit 'a = [0] * 100000' 'while a: a.pop()'
  • (给出了速度差异的数量级,其中第二个示例使用CPython和PyPy时速度更快)。*

1.在这种情况下,您可以考虑使用set,尤其是当列表不打算存储重复项时。
在实践中,你可能需要存储可变的数据,这些数据不能被添加到set中。还要检查btree的数据是否可以排序。

3zwjbxry

3zwjbxry6#

咦,不要做任何复杂的事情:)
bool()返回空字符串的False,因此,

new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)

你应该写

new_tag_list = filter(bool, f1.striplist(tag_string.split(",") + selected_tags))

或者更好的方法是将此逻辑放在striplist()中,这样它就不会首先返回空字符串。

nszi6y05

nszi6y057#

这里有另一个简单的方法:

next((some_list.pop(i) for i, l in enumerate(some_list) if l == thing), None)

它不创建列表副本,不多次遍历列表,不需要额外的异常处理,并且返回匹配的对象,如果不匹配则返回None。唯一的问题是它需要一个很长的语句。
一般来说,当寻找一个不抛出异常的单行程序解决方案时,next()是最好的选择,因为它是少数支持默认参数的Python函数之一。

euoag5mw

euoag5mw8#

你要做的就是

list = ["a", "b", "c"]
    try:
        list.remove("a")
    except:
        print("meow")

但是这个方法有个问题,你必须在except的地方放一些东西,所以我发现了这个:

list = ["a", "b", "c"]
if "a" in str(list):
    list.remove("a")
lqfhib0f

lqfhib0f9#

1-使用筛选选项

新标签列表= [u ',u'你好',u'酷',u'魅力']
new_tag_list=列表(过滤器(无,新标记列表))

2-列表解析同样适用于None以外的元素

新标签列表= [u ',u'你好',u'酷',u'魅力']
[如果元素不在[''中,则new_tag_list中元素的元素]

相关问题