Python-从作为另一个元素的子字符串的字符串列表中删除任何元素

Python-从作为另一个元素的子字符串的字符串列表中删除任何元素,python,string,list,substring,Python,String,List,Substring,从字符串列表开始,如下所示 string_list=['rest','rest','look','looked','it','spit'] 我想从列表中删除作为另一个元素的子字符串的任何元素,例如给出结果 string_list=['resting','looked','spit'] 我有一些代码可以解决这个问题,但它非常难看,而且可能不必要地复杂。在Python中有没有一种简单的方法可以做到这一点?这里有一个可能的解决方案: string_list = ['rest', 'resting',

从字符串列表开始,如下所示

string_list=['rest','rest','look','looked','it','spit']

我想从列表中删除作为另一个元素的子字符串的任何元素,例如给出结果

string_list=['resting','looked','spit']


我有一些代码可以解决这个问题,但它非常难看,而且可能不必要地复杂。在Python中有没有一种简单的方法可以做到这一点?

这里有一个可能的解决方案:

string_list = ['rest', 'resting', 'look', 'looked', 'it', 'spit']
def string_set(string_list):
    return set(i for i in string_list 
               if not any(i in s for s in string_list if i != s))

print(string_set(string_list))
打印出:

set(['looked', 'resting', 'spit'])
注意:我创建了一个集合(使用生成器表达式)来删除可能重复的单词,因为顺序似乎无关紧要。

这里有一个方法:

def find_unique(original):
    output = []

    for a in original:
        for b in original:
            if a == b:
                continue     # So we don't compare a string against itself
            elif a in b:
                break
        else:
            output.append(a) # Executed only if "break" is never hit

    return output

if __name__ == '__main__':
    original = ['rest', 'resting', 'look', 'looked', 'it', 'split']
    print find_unique(original)
它利用了这样一个事实,即我们可以通过使用
in
操作符轻松检查一个字符串是否是另一个字符串的子字符串。它基本上遍历每个字符串,检查它是否是另一个字符串的子字符串,如果不是,则将自身附加到输出列表中


这将打印出
['rest'、'looked'、'split']

这是一个可以满足您需要的单行程序:

filter(lambda x: [x for i in string_list if x in i and x != i] == [], string_list)
例如:

>>> string_list = ['rest', 'resting', 'look', 'looked', 'it', 'spit']
>>> filter(lambda x: [x for i in string_list if x in i and x != i] == [], string_list)
['resting', 'looked', 'spit']
另一艘班轮:

[string for string in string_list if len(filter(lambda x: string in x,string_list)) == 1]

应该是相当可读的,只是不是那种pythonic。

第一个构建块:子字符串

您可以使用中的
检查:

>>> 'rest' in 'resting'
True
>>> 'sing' in 'resting'
False
接下来,我们将选择创建新列表的简单方法。我们将逐一将项目添加到新列表中,检查它们是否为子字符串

def substringSieve(string_list):
    out = []
    for s in string_list:
        if not any([s in r for r in string_list if s != r]):
            out.append(s)
    return out
您可以通过排序来减少比较的数量来加快速度(毕竟,较长的字符串永远不能是较短/等长字符串的子字符串):


以下是一种非最佳方法,仅在列表较小时使用:

for str1 in string_list:
    for str2 in string_list:
        if str1 in str2 and str1 != str2:
            string_list.remove(str1)

这是一种有效的方法(相对于上述解决方案;),因为这种方法大大减少了列表元素之间的比较次数。如果我有一个巨大的列表,我肯定会使用这个,当然你可以将这个解决方案变形为一个lambda函数,使它看起来很小:

string_list = ['rest', 'resting', 'look', 'looked', 'it', 'spit']
for item in string_list: 
  for item1 in string_list:
    if item in item1 and item!= item1:
      string_list.remove(item)

print string_list
输出:

>>>['resting', 'looked', 'spit']

希望有帮助

还有另一种方法。假设您有一个排序列表开始,并且您不必就地进行筛选,我们只需在一次过程中选择最长的字符串:

string_list = sorted(string_list)
sieved = []
for i in range(len(string_list) - 1):
    if string_list[i] not in string_list[i+1]:
        sieved.append(string_list[i])

让我们看看这个难看的版本。这将是一个很好的。。。破冰者我从来没有见过有人在一个问题中因为他们的代码而被嘲笑。前几天我问了一个类似的问题。一个类似的问题,可能有更高性能的解决方案。刚修好。注意,对于Python3,filter返回一个迭代器,因此这可能会引发
TypeError:type'filter'的对象没有len()
。只需将
过滤器
包装为
列表
len(列表(过滤器(lambda x:string in x,string_list))
。此外,如果
字符串_列表
哈希重复,例如
['apple','apple']
。这将返回一个空列表,而不是
['apple']
。这种行为可能是我们想要的,也可能不是我们想要的。
string_list = sorted(string_list)
sieved = []
for i in range(len(string_list) - 1):
    if string_list[i] not in string_list[i+1]:
        sieved.append(string_list[i])