如何找到以任意顺序匹配子字符串的字符串?

How to find a string that match a substring in any order?

假设列表如下:

list_of_strings = ['foo', 'bar', 'soap', 'seo', 'paseo', 'oes']

和一个子字符串

to_find = 'eos'

我想在 list_of_strings 中找到与子字符串匹配的字符串。 list_of_strings 的输出应该是 ['seo', 'paseo', 'oes'](因为它包含 to_find 子字符串中的所有字母)

我尝试了几件事:

a = next((string for string in list_of_strings if to_find in string), None) # gives NoneType object as output

&

result = [string for string in list_of_strings if to_find in string] # gives [] as output

但这两个代码都不起作用。

谁能告诉我我做错了什么?

谢谢

您的问题在逻辑上是将要查找的单词中的 字符与列表中每个单词中的 字符进行比较.如果后一个单词包含要查找的单词中的所有字符,则它是一个匹配项。这是一种使用列表理解和集合 intesection:

的方法
list_of_strings = ['foo', 'bar', 'soap', 'seo', 'paseo', 'oes']
to_find = 'eos'
to_find_set = set(list(to_find))
output = [x for x in list_of_strings if len(to_find_set.intersection(set(list(x)))) == len(to_find_set)]
print(output)  # ['seo', 'paseo', 'oes']

如果您想为 匹配的任何输入字符串保留空字符串占位符,请使用此版本:

output = [x if len(to_find_set.intersection(set(list(x)))) == len(to_find_set) else '' for x in list_of_strings]
print(output)  # ['', '', '', 'seo', 'paseo', 'oes']

您需要 to_find 的字母彼此相邻还是所有字母都应该在单词中?基本上: seabco 是否匹配?

[你的问题不包括这个细节,你经常使用“substring”,但也“因为它包含 to_find 中的所有字母”,所以我不确定如何解释它。 ]

如果 seabco 匹配,则@Tim Biegeleisen 的答案是正确的。如果字母需要并排(当然可以任意顺序),请看下面:


如果to_find比较短,你可以只生成字母的所有排列(n!,所以这里(3!)= 6:eos, eso, oes, ose, seo, soe) 并检查 in.

import itertools
list_of_strings = ['foo', 'bar', 'soap', 'seo', 'paseo', 'oes']
to_find = 'eos'

result = [string for string in list_of_strings if any("".join(perm) in string for perm in itertools.permutations(to_find))]

https://docs.python.org/3/library/itertools.html#itertools.permutations

我们这样做 "".join(perm) 因为 perm 是一个元组,我们需要一个字符串。

>>> result = [string for string in list_of_strings if any("".join(perm) in string for perm in itertools.permutations(to_find))]
>>> result
['seo', 'paseo', 'oes']

Less-obvious 但更复杂的是只获取字符串的 3 个字符的子字符串(使它们彼此相邻)和 set-compare 将它们设置为 to_find。

list_of_strings = ['foo', 'bar', 'soap', 'seo', 'paseo', 'oes']
to_find = 'eos'

result = [string for string in list_of_strings if any(set(three_substring)==set(to_find) for three_substring in zip(string, string[1:], string[2:]))]