当前位置:  开发笔记 > 编程语言 > 正文

在Python中从序列中删除项目的优雅方法?

如何解决《在Python中从序列中删除项目的优雅方法?》经验,为你挑选了4个好方法。

当我在Python中编写代码时,我经常需要根据某些条件从列表或其他序列类型中删除项目.我还没有找到优雅高效的解决方案,因为从当前正在迭代的列表中删除项目是不好的.例如,你不能这样做:

for name in names:
    if name[-5:] == 'Smith':
        names.remove(name)

我通常最终做这样的事情:

toremove = []
for name in names:
    if name[-5:] == 'Smith':
        toremove.append(name)
for name in toremove:
    names.remove(name)
del toremove

这是无效的,相当丑陋和可能有错误(它如何处理多个'John Smith'条目?).有没有人有更优雅的解决方案,或者至少更有效?

那个与词典一起工作的人怎么样?



1> John..:

完成过滤的两种简单方法是:

    使用filter:

    names = filter(lambda name: name[-5:] != "Smith", names)

    使用列表推导:

    names = [name for name in names if name[-5:] != "Smith"]

请注意,这两种情况都保留谓词函数评估的值True,因此您必须反转逻辑(即您说"保留没有姓氏史密斯的人"而不是"删除姓氏的人")史密斯").

编辑搞笑...两个人分别发布了我建议的两个答案,因为我发布了我的答案.


`not name.endswith("Smith")`看起来好多了:-)
当然,如果你喜欢可读性或其他什么.
@Sevenearths:"[ - 5:]"取名字的最后五个字符,因为我们想知道名字是否以"Smith"结尾.正如Jochen所说,"name [: - 5]!='Smith'"的表达可能更容易被写为"not name.endswith('Smith')".

2> 小智..:

您还可以在列表上向后迭代:

for name in reversed(names):
    if name[-5:] == 'Smith':
        names.remove(name)

这样做的好处是它不会创建新列表(如filter列表推导)或使用迭代器而不是列表副本(如[:]).

请注意,尽管在向后迭代时删除元素是安全的,但插入它们有点棘手.



3> Edward Loper..:

显而易见的答案是约翰和其他几个人给出的答案,即:

>>> names = [name for name in names if name[-5:] != "Smith"]       # <-- slower

但是它的缺点是它创建了一个新的列表对象,而不是重用原始对象.我做了一些分析和实验,我提出的最有效的方法是:

>>> names[:] = (name for name in names if name[-5:] != "Smith")    # <-- faster

分配给"names [:]"基本上意味着"用以下值替换名称列表的内容".它与仅仅分配名称不同,因为它不会创建新的列表对象.赋值的右侧是生成器表达式(注意使用括号而不是方括号).这将导致Python在列表中进行迭代.

一些快速分析表明,这比列表理解方法快约30%,比过滤方法快约40%.

警告:虽然这个解决方案比明显的解决方案更快,但它更加模糊,并且依赖于更先进的Python技术.如果您使用它,我建议随附评论.在你真正关心这个特定操作的性能的情况下,这可能是值得使用的(无论如何都非常快).(在我使用它的情况下,我正在进行A*光束搜索,并使用它来从搜索光束中删除搜索点.)


真的很有趣的性能发现.你能分享一下你的分析环境和评估方法吗?

4> Corey..:

使用列表理解

list = [x for x in list if x[-5:] != "smith"]

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有