在Python中从列表中删除列表子集的最快方法

在Python中从列表中删除列表子集的最快方法,python,python-2.7,subset,itertools,superset,Python,Python 2.7,Subset,Itertools,Superset,假设我有一个列表,如下所示(实际列表要长得多): 在本例中,列表中的所有项目['banana','pear'],['apple','pear']和['apple','pear','banana']都包含在列表中['apple','pear','banana','西瓜'](项目的顺序无关紧要),因此我想删除['banana pear','pear'],['apple'、'pear']和['apple'、'pear'、'banana'],因为它们是['apple'、'pear'、'banana'、'

假设我有一个列表,如下所示(实际列表要长得多):

在本例中,列表中的所有项目
['banana','pear']
['apple','pear']
['apple','pear','banana']
都包含在列表中
['apple','pear','banana','西瓜']
(项目的顺序无关紧要),因此我想删除
['banana pear','pear']
['apple'、'pear']
['apple'、'pear'、'banana']
,因为它们是
['apple'、'pear'、'banana'、'西瓜']
的子集

我当前的解决方案如下所示。我首先使用
ifilter
imap
为每个列表可能具有的超集创建一个生成器。然后,对于确实具有超集的情况,我使用
compress
imap
删除它们

from itertools import imap, ifilter, compress

supersets = imap(lambda a: list(ifilter(lambda x: len(a) < len(x) and set(a).issubset(x), fruits)), fruits)


new_list = list(compress(fruits, imap(lambda x: 0 if x else 1, supersets)))
new_list
#[['pear', 'pineapple'], ['apple', 'pear', 'banana', 'watermelon']]
从itertools导入imap、ifilter、compress
超集=imap(lambda:list(ifilter(lambda x:len(a)
我想知道是否有更有效的方法来做这件事?我不知道它是否更快,但这更容易阅读(对我来说):


更新

它很快。更快的方法是对
循环使用
。检查计时:

fruits = [['apple', 'pear'],
        ['apple', 'pear', 'banana'],
        ['banana', 'pear'],
        ['pear', 'pineapple'],
        ['apple', 'pear', 'banana', 'watermelon']]

from itertools import imap, ifilter, compress    

def f1():              
    sets={frozenset(e) for e in fruits}  
    us=[]
    while sets:
        e=sets.pop()
        if any(e.issubset(s) for s in sets) or any(e.issubset(s) for s in us):
            continue
        else:
            us.append(list(e))   
    return us           

def f2():
    supersets = imap(lambda a: list(ifilter(lambda x: len(a) < len(x) and set(a).issubset(x), fruits)), fruits)
    new_list = list(compress(fruits, imap(lambda x: 0 if x else 1, supersets)))
    return new_list

def f3():
    return filter(lambda f: not any(set(f) < set(g) for g in fruits), fruits)

def f4():              
    sets={frozenset(e) for e in fruits}  
    us=[]
    for e in sets:
        if any(e < s for s in sets):
            continue
        else:
            us.append(list(e))   
    return us              

if __name__=='__main__':
    import timeit     
    for f in (f1, f2, f3, f4):
        print f.__name__, timeit.timeit("f()", setup="from __main__ import f, fruits"), f()  
过滤器(lambda f:无任何(水果中g的集合(f)<集合(g)),水果)

您可以先删除imap和ifilter来使用生成器表达式/列表理解。它们的工作方式相同,但生成可读的代码…@BrentWashburne这不完全是重复的。正如您所看到的,我当前的解决方案实际上使用了
issubset()
正如链接帖子所建议的。我的问题更多的是关于如何删除大列表中其他列表的子集。@JBernardo:你能举个例子吗?谢谢!:)@dawg:对不起,忘了更改代码。
foo
应该是
超集
。我在尝试你的代码时更新了它,得到了
[苹果、梨、香蕉、香蕉、菠萝、菠萝、苹果、梨、香蕉、西瓜
我的代码中有一个错误。我认为当前版本应该可以运行。无论你采用哪种方式,它都对我有效——而且无论哪种方式,这都是一个类似于python的答案。这让我很高兴。很奇怪。在Canopy编辑器界面中,我一直得到一个空列表。但当我在命令行界面中尝试时,我得到了正确的结果!感谢我的尝试d
f1()
,结果我得到了
set()!
sets={frozenset(e) for e in fruits}  
us=set()
while sets:
    e=sets.pop()
    if any(e.issubset(s) for s in sets) or any(e.issubset(s) for s in us):
        continue
    else:
        us.add(e)   
fruits = [['apple', 'pear'],
        ['apple', 'pear', 'banana'],
        ['banana', 'pear'],
        ['pear', 'pineapple'],
        ['apple', 'pear', 'banana', 'watermelon']]

from itertools import imap, ifilter, compress    

def f1():              
    sets={frozenset(e) for e in fruits}  
    us=[]
    while sets:
        e=sets.pop()
        if any(e.issubset(s) for s in sets) or any(e.issubset(s) for s in us):
            continue
        else:
            us.append(list(e))   
    return us           

def f2():
    supersets = imap(lambda a: list(ifilter(lambda x: len(a) < len(x) and set(a).issubset(x), fruits)), fruits)
    new_list = list(compress(fruits, imap(lambda x: 0 if x else 1, supersets)))
    return new_list

def f3():
    return filter(lambda f: not any(set(f) < set(g) for g in fruits), fruits)

def f4():              
    sets={frozenset(e) for e in fruits}  
    us=[]
    for e in sets:
        if any(e < s for s in sets):
            continue
        else:
            us.append(list(e))   
    return us              

if __name__=='__main__':
    import timeit     
    for f in (f1, f2, f3, f4):
        print f.__name__, timeit.timeit("f()", setup="from __main__ import f, fruits"), f()  
f1 8.09958791733 [['watermelon', 'pear', 'apple', 'banana'], ['pear', 'pineapple']]
f2 15.5085151196 [['pear', 'pineapple'], ['apple', 'pear', 'banana', 'watermelon']]
f3 11.9473619461 [['pear', 'pineapple'], ['apple', 'pear', 'banana', 'watermelon']]
f4 5.87942910194 [['watermelon', 'pear', 'apple', 'banana'], ['pear', 'pineapple']]
filter(lambda f: not any(set(f) < set(g) for g in fruits), fruits)