8

我想在保持顺序的同时找到嵌套列表之间的交集。

taxa = [['E_pyrifoliae_Ep1_96', 'Bacteria', 'Proteobacteria', 'Gammaproteobacteria', 'Enterobacteriales', 'Enterobacteriaceae', 'Erwinia'],
 ['E_amylovora_CFBP1430', 'Bacteria', 'Proteobacteria', 'Gammaproteobacteria', 'Enterobacteriales', 'Enterobacteriaceae', 'Erwinia'], 
 ['E_amylovora_ATCC49946', 'Bacteria', 'Proteobacteria', 'Gammaproteobacteria', 'Enterobacteriales', 'Enterobacteriaceae', 'Erwinia']]

要找到我的交叉点:

set.intersection(*map(set, taxa))

或者

set(taxa[0]).intersection(*taxa)

但不保留原来的顺序。

set(['Erwinia', 'Gammaproteobacteria', 'Enterobacteriaceae', 'Enterobacteriales', 'Proteobacteria', 'Bacteria'])

基本上,我需要做的是找到嵌套列表之间的最后一个共同元素(它们是分类学分类)。所以当我可以调用最后一个条目时,我不需要找到所有的交叉点,只需要找到最后一个或所有交叉点。

intersection_lst[-1]

在这种情况下,我希望输出为“Erwinia”。

谢谢你的帮助。

4

4 回答 4

7

找到交叉点,然后重新排序。

intersection_set = set.intersection(*map(set, taxa))
intersection_lst = [t for t in taxa[0] if t in intersection_set]

或者,如果您非常喜欢单线:

sorted(set.intersection(*map(set, taxa)), key=lambda x: taxa[0].index(x))
于 2012-08-14T17:06:20.867 回答
0

您可以通过以下方式获得:

[t for t in taxa[0] if all(t in l for l in taxa)]
# ['Bacteria', 'Proteobacteria', 'Gammaproteobacteria', 'Enterobacteriales', 'Enterobacteriaceae', 'Erwinia']

如果列表很大,这样做会更有效率:

taxa_set = map(set, taxa)    
[t for t in taxa[0] if all(t in l for l in taxa_set)]
于 2012-08-14T16:59:38.897 回答
0
from collections import OrderedDict
from itertools import chain

d=OrderedDict()
for elem in chain(*taxa):
    if elem in d:
        d[elem] += 1
    else:
        d[elem] = 1

intersection_lst = [ k for k,v in d.items() if v == len(taxa) ]

请注意,这仅在内部列表是唯一的情况下才有效。

这是一个使用有序计数器的示例:

from collections import OrderedDict,Counter
from itertools import chain

class OrderedCounter(Counter,OrderedDict): pass

d = OrderedCounter(chain(*taxa))
intersection_lst = [ k for k,v in d.items() if v == len(taxa) ]

仅当元素在每个子列表中都是唯一的时才有效

于 2012-08-14T17:02:31.140 回答
0

我今天遇到了类似的问题。在我的基准测试中,使用set.intersection是在 CPython 中实现这一目标的最快方法,我的数据集大约需要 170us。

然而,在 PyPy 中,利用排序的手动函数只需要大约 80 微秒,几乎是 CPython 速度的两倍!CPython 中的相同函数耗时约 6200us。

这是后代的功能:

def intersect_ordered(a, b):
    matches = []
    ia, ib = 0, 0
    la, lb = len(a), len(b)
    while ia < la and ib < lb:
        va, vb = a[ia], b[ib]
        if va < vb:
            ia += 1
        elif vb < va:
            ib += 1
        else:
            matches.append(va)
            ia += 1
            ib += 1
    return matches
于 2013-02-08T22:00:32.737 回答