如何删除列表中的项目(如果存在)?

新手上路,请多包涵

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

self.response.get_all("selected_tags")

我这样组合它们:

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

f1.striplist 是一个去除列表中字符串内空格的函数。)

But in the case that tag_list is empty (no new tags are entered) but there are some selected_tags , new_tag_list contains an empty string " "

例如,来自 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

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

原文由 Zeynel 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 150
2 个回答

1)几乎是英文风格:

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

 if thing in some_list: some_list.remove(thing)

The remove method will remove only the first occurrence of thing , in order to remove all occurrences you can use while instead of 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 子句不仅幽默有问题,而且完全没有必要(重点是为不熟悉该概念的人说明鸭子类型)。

如果您期望事物多次出现:

 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)功能风格:

Around 1993, Python got lambda , reduce() , filter() and map() , courtesy of a Lisp hacker who missed them and submitted working patches* .您可以使用 filter 从列表中删除元素:

 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)

  • [update] : in Python 2.x, filter(function, iterable) used to be equivalent to [item for item in iterable if function(item)] (or [item for item in iterable if item] if the first argument is None );在 Python 3.x 中,它现在等同于 (item for item in iterable if function(item)) 。细微的区别是过滤器用于返回一个列表,现在它像一个生成器表达式一样工作——如果你只是迭代清理过的列表并丢弃它,这是可以的,但如果你真的需要一个列表,你必须把 filter() 调用 list() 构造函数。
  • *这些 Lispy 风格的构造在 Python 中被认为有点陌生。 Around 2005, Guido was even talking about dropping filter - along with companions map and reduce (they are not gone yet but reduce was移入 functools 模块,如果你喜欢 高阶函数,值得一看)。

4)数学风格:

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

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

生成器表达式由 PEP 289 在 2.4 版中引入。生成器表达式更适用于您不需要(或不想)在内存中创建完整列表的情况——比如您只想一次迭代一个元素。如果您只是遍历列表,您可以将生成器表达式视为 惰性评估 列表理解:

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

笔记

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

原文由 Paulo Scardine 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

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

原文由 Tim Pietzcker 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题