从列表中删除最后出现的包含子字符串的元素

时间:2019-09-26 15:21:13

标签: python python-2.7 string-search

所以说我有list1 = [“狗”,“猫”,“猫狗”,“狗跑回家”]

和sub_string ='狗'

我如何返回list2 = ['狗','猫','猫狗']

,即返回一个列表,其中删除了最后出现的子字符串?

5 个答案:

答案 0 :(得分:2)

这里没有内置功能对您有很大帮助,因为不支持扫描list中的子字符串,并且以相反的顺序进行扫描非常困难。列表理解也不是一件好事,因为使它们具有足够的状态以识别何时发现您的针头会给列表理解增加副作用,这使其变得晦涩难懂并违反了功能编程工具的目的。因此,您无法自己进行循环:

list2 = []
list1iter = reversed(list1)  # Make a reverse iterator over list1
for item in list1iter:
    if sub_string in item:   # Found item to remove, don't append it, we're done
        break
    list2.append(item)       # Haven't found it yet, keep item
list2.extend(list1iter)      # Pull all items after removed item
list2.reverse()              # Put result back in forward order

Try it online!

另一种方法是按索引扫描,使您可以del进行索引;如果您想就地修改list1而不是新建一个list,这可能是一个更好的解决方案:

for i, item in enumerate(reversed(list1), 1):
    if sub_string in item:
        del list1[-i]
        break

Try it online!

该解决方案适用于制作新副本,只需将所有对list1的引用更改为list2,并在循环之前添加list2 = list1[:]

在两种情况下,您都可以通过在else:上放置for块来检测是否找到了所有项目;如果else块触发,则您没有break,因为在任何地方都找不到sub_string

答案 1 :(得分:2)

问题陈述是:删除带有子字符串作为查询的元素

所以,据我推断,它有两个步骤。

  1. 使用子字符串查找元素。
  2. 删除元素。

对于模式匹配,我们可以使用re模块(我们可以使用in以及ShadowRanger的答案中提到的内容)

import re

pattern = re.compile('the dog') # target pattern 
my_list = ['the dog', 'the cat', 'cat dog', 'the dog ran home'] # our list
my_list = enumerate(my_list) # to get indexes corresponding to elemnts i.e. [(0, 'the dog'), (1, 'the cat'), (2, 'cat dog'), (3, 'the dog ran home')]
elems = list(filter(lambda x: pattern.search(x[1]), my_list) # match the elements in the second place and filter them out, remember filter in python 3.x returns an iterator
print(elems) # [(0, 'the dog'), (3, 'the dog ran home')]
del my_list[elems[-1][0]] # get the last element and take the index of it and delete it.

编辑

如ShadowRunner建议的那样,我们可以使用带有if语句的列表理解而不是filter函数来优化代码。

elems = [i for i, x in enumerate(my_list) if pattern.search(x)]

答案 2 :(得分:1)

您可以分两个步骤进行操作:

  1. 找到最后一次出现的索引。
  2. 返回所有与该索引不匹配的元素。

示例:

needle = 'the dog'
haystack = ['the dog', 'the cat', 'cat dog', 'the dog ran home']

last = max(loc for loc, val in enumerate(haystack) if needle in val)
result = [e for i, e in enumerate(haystack) if i != last]

print(result)

输出

['the dog', 'the cat', 'cat dog']

有关查找最后一次出现的索引的更多详细信息,请参见this

答案 3 :(得分:1)

list1 = ['the dog', 'the cat','the dog me', 'cat dog']
sub_string = 'the dog'

for i in list1[::-1]:
    print(i)
    if sub_string in i:
        list1.remove(i)
        break

输出 [“狗”,“猫”,“狗我”,“猫狗”]

答案 4 :(得分:1)

一种解决方案是以相反的顺序遍历输入并在反向列表中找到索引。之后,使用索引对输入list1进行切片。

idx = next(i for i, s in enumerate(reversed(list1), 1) if sub_string in s)
list2 = list1[:-idx]  # If in-place updates are intended, use `del list1[-idx:]` instead