[英]Python: intersection of nested lists where order matters
我想在維護順序的同時找到嵌套列表之間的交集。
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'。
謝謝你的幫助。
找到交叉點,然后重新獲得訂單。
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))
您可以通過以下方式獲得:
[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)]
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) ]
如果元素在每個子列表中都是唯一的,則仍然有效
我今天遇到了類似的問題。 在我的基准測試中,使用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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.