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'])

基本的に、私が行う必要があるのは、ネストされたリスト間の最後の共通要素を見つけることです(これらは分類学的分類です)。したがって、すべての交差点を見つける必要はありません。最後のエントリを呼び出すことができる場合は、最後の1つまたはすべての交差点を見つける必要があります。

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

今日も同様の問題がありました。私のベンチマークでset.intersectionは、CPython でこれを達成するための最速の方法は使用であり、データセットで約 170us かかりました。

しかし、PyPy では、順序付けを利用した手巻き関数はわずか 80us しかかからず、CPython のほぼ 2 倍の速度です。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 に答える
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 に答える