Python 检查列表元素是否为同一列表中其他列表元素的子元素

Python 检查列表元素是否为同一列表中其他列表元素的子元素,python,list,Python,List,我正在寻找一种方法来检查列表中的一个元素是否是同一列表中任何其他元素的子元素 例如,让我们以下面的列表为例 ['Lebron James', 'Lebron', 'James'] 此列表的第二和第三个元素是列表第一个元素的子元素 我正在寻找从列表中删除这些元素的方法,以便只保留第一个元素。我一直在打转,想不出解决办法 有人能帮忙吗 谢谢这是一个缓慢的解决方案,可能可以接受,具体取决于您的数据大小: lst = ['Lebron James', 'Lebron', 'James'] [s for

我正在寻找一种方法来检查列表中的一个元素是否是同一列表中任何其他元素的子元素

例如,让我们以下面的列表为例

['Lebron James', 'Lebron', 'James']
此列表的第二和第三个元素是列表第一个元素的子元素

我正在寻找从列表中删除这些元素的方法,以便只保留第一个元素。我一直在打转,想不出解决办法

有人能帮忙吗


谢谢

这是一个缓慢的解决方案,可能可以接受,具体取决于您的数据大小:

lst = ['Lebron James', 'Lebron', 'James']
[s for s in lst if not any(s in s2.split() for s2 in lst if s != s2)]

创建一个包含字符串中多个单词的所有单词的集合。然后检查列表,测试字符串是否在集合中

wordset = set()
lst = ['Lebron James', 'Lebron', 'James']
for s in lst:
    if " " in s:
        wordset.update(s.split())
result = [x for x in lst if x not in wordset]


这绝对是一个更容易解决的问题,比赛的起点和终点,而不是字符串本身

一种方法是将所有范围从最大值到最小值,然后反向工作,在你前进的过程中创建结果,因为一个范围没有完全包含在另一个范围中

lst = [(0, 10),(0, 4),(5, 10)]

result = []

def memebership(big_range, small_range):
    '''return true if big_range fully contains the small_range.
    where both are tuples with a start and end value.
    '''
    if small_range[0] >= big_range[0] and small_range[1] <= big_range[1]:
        return True
    return False

for range_ in sorted(lst, key= lambda x: x[1] - x[0], reverse=True):
    if not any(memebership(x, range_) for x in result):
        result.append(range_)

print(result)
#[(0, 10)]
lst=[(0,10)、(0,4)、(5,10)]
结果=[]
def成员身份(大范围、小范围):
''如果大\u范围完全包含小\u范围,则返回true。
其中两者都是具有起始值和结束值的元组。
'''

如果small_range[0]>=big_range[0]和small_range[1]可以尝试创建一个按元素字数分组的所有排列的字典(排列、子列表或任何选择取决于所需的行为):

import re
import itertools
from collections import defaultdict

lst = [
    'Lebron Raymone James', 'Lebron Raymone', 
    'James', "Le", "Lebron James", 
    'Lebron James 1 2 3', 'Lebron James 1 2'
]

d = defaultdict(dict)
g = "\\b\w+\\b"

for x in lst:
    words = re.findall(g, x)  # could simply use x.split() if have just spaces
    combos = [
        x for i in range(1, len(words) + 1)
        for x in list(itertools.permutations(words, i))
    ]
    for c in combos:
        d[len(words)][tuple(c)] = True
只取单词不在任何一组中且单词数较大的元素:

M = max(d) 
res = []
for x in lst:
    words = tuple(re.findall(g, x))
    if not any(d[i].get(words) for i in range(len(words)+1, M+1)):
        res.append(x)
set(res)
# {'Le', 'Lebron James 1 2 3', 'Lebron Raymone James'}

@yatu不,列表中的元素数量可能会有所不同。不,但是下面@Alex的解决方案效果很好。它是否必须匹配较长字符串或任何子字符串中的整个单词?例如,
['Lebron James','Le']
的第二个元素应该被返回吗?我没有想到这一点,但它可能应该是完整的匹配。好的一点-你对如何修改下面的解决方案有什么想法吗?另外:看起来不必要O(n**2)@wim这就是为什么他说这是一个缓慢的解决方案。当他回答OP只想匹配整个单词而不是任何子字符串的评论时,速度会变慢。你的算法很糟糕。考虑输入<代码> [’LeBron杰姆斯1 2 3’,“勒布朗·詹姆斯1 2”] < /代码>我不确定这是否是他想要过滤掉的东西,我们应该ASK。它应该是<代码>成员< /代码>?当时无法想出一个更好的名字。P任何你想称之为大范围的名称,完全封装一个小范围的名称可以根据你的判断进行调整。