首页 > 解决方案 > Remove string in list that is substring of another string if both are in the list

问题描述

Imagine you have a list of lists as follows:

list = [['Hello','Hello World','something else'],
 ['Hello','something'],
 ['somethings']
 ['Hello World','something else'],
 ['Hello','blabla','Hello World']]

I would like to remove the 'Hello' in the list if and only if 'Hello World' is in it.

What I have tried:

new_list = [elem.remove('Hello') for elem in lista if 'Hello' and 'Hello World' in elem]

However, I get the following error:

list.remove(x): x not in list

And my list becomes this:

[['Hello World', 'something else'],
 ['Hello', 'something'],
 ['somethings'],
 ['Hello World', 'something else'],
 ['Hello', 'blabla', 'Hello World']]

So it worked for the first row, but then it broke.

Extra points for computational efficiency!

标签: pythonstringlist

解决方案


问题出在这里:

if 'Hello' and 'Hello World' in elem

这并不像您认为的那样起作用。if 'Hello'是一个单独的子句,它总是计算为True因为'Hello'不是空字符串。您需要两次写出完整的测试:

if 'Hello' in elem and 'Hello World' in elem

另外,将其写为列表推导不太有意义,因为它list.remove修改了原始列表,并且不返回任何内容。你的new_list意志只是充满None。只需使用一个for循环:

for sub_list in my_list:  # also note, you should not use `list` as a variable name. 
    if 'Hello' in sub_list and 'Hello World' in sub_list:
        sub_list.remove('Hello')

如果您实际上不想修改原始列表/子列表,则需要显式创建新列表而不是使用remove

new_list = []
for sub_list in my_list:
    if 'Hello World' in sub_list:
        new_sub_list = [elem for elem in sub_list if elem != 'Hello']
    else:
        new_sub_list = sub_list[:] # make a copy to avoid referencing the original
    new_list.append(new_sub_list)

如果你愿意,这整个事情可以写成一个嵌套的列表理解:

new_list = [sub_list[:] if 'Hello World' not in sub_list else 
            [elem for elem in sub_list if elem != 'Hello']
            for sub_list in my_list]

但在任何一种情况下,为了清楚起见,我可能更喜欢显式的 for 循环构造。


推荐阅读