我想在维护顺序的同时找到嵌套列表之间的交集。
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'。
感谢您的帮助。
答案 0 :(得分: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))
答案 1 :(得分: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)]
答案 2 :(得分: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) ]
如果元素在每个子列表中都是唯一的 ,仍然有效
答案 3 :(得分:0)
我今天遇到了类似的问题。在我的基准测试中,使用set.intersection
是在CPython中实现这一目标的最快方法,使用我的数据集大约需要170us。
然而,在PyPy中,利用排序的手动功能只需要大约80us,几乎是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