14

辞書d1とリストがありl1ます。

辞書キーは文字列であり、値は自分で定義したオブジェクトです。役立つ場合は、オブジェクトをより詳細に説明できますが、現時点では、オブジェクトにはリスト属性namesがあり、の要素の一部はにname表示される場合と表示されない場合がありますl1

私がやりたかったのは、辞書の要素を破棄することでした。この要素のオブジェクトd1name属性には、に表示される要素が含まれていませんl1

簡単な例として:

l1 = ['cat', 'dog', 'mouse', 'horse', 'elephant', 
      'zebra', 'lion', 'snake', 'fly']

d1 = {'1':['dog', 'mouse', 'horse','orange', 'lemon'],
      '2':['apple', 'pear','cat', 'mouse', 'horse'], 
      '3':['kiwi', 'lime','cat', 'dog', 'mouse'], 
      '4':['carrot','potato','cat', 'dog', 'horse'], 
      '5':['chair', 'table', 'knife']}

1したがって、結果のディクショナリはほぼ同じになりますが、各リストの要素は、果物と野菜を除くからのキーと値のペア4になり、家具の値が表示されないため、5番目のキーと値のパーは含まれません。l1

これを行うために、私は次のようなネストされたリスト/辞書の理解を使用しました:

d2 = {k: [a for a in l1 if a in d1[k]] for k in d1.keys()}
print(d2)

>>>>{'1': ['dog', 'mouse', 'horse'], 
     '3': ['cat', 'dog', 'mouse'], 
     '2': ['cat', 'mouse', 'horse'], 
     '5': [], 
     '4': ['cat', 'dog', 'horse']}

d2 = {k: v for k,v in d2.iteritems() if len(v)>0}
print(d2)

>>>>{'1': ['dog', 'mouse', 'horse'], 
     '3': ['cat', 'dog', 'mouse'], 
     '2': ['cat', 'mouse', 'horse'],  
     '4': ['cat', 'dog', 'horse'],}

これは機能しているように見えますが、7000以上の大きな辞書の場合、処理には約20秒かかります。それ自体は恐ろしいことではありませんが、10,000回繰り返されるループ内でこれを行う必要があるため、現在は実行できません。これをすばやく行う方法について何か提案はありますか?

4

5 に答える 5

14

ディクショナリ値で発生する各リストとリストの集合の共通部分を効果的に計算していますl1。セット交差点にリストを使用することは、線形検索が含まれるため、かなり非効率的です。代わりに、セットに変換してメンバーシップテストl1を使用または設定する必要があります(結果が再びセットであることが許容できるかどうかによって異なります)。set.intersection()

完全なコードは次のようになります。

l1 = set(l1)
d2 = {k: [s for s in v if s in l1] for k, v in d1.iteritems()}
d2 = {k: v for k, v in d2.iteritems() if v}

for2つの辞書内包表記の代わりに、ここで1つのループを使用することも望ましい場合があります。

l1 = set(l1)
d2 = {}
for k, v in d1.iteritems():
    v = [s for s in v if s in l1]
    if v:
        d2[k] = v
于 2012-08-10T14:08:51.847 に答える
4

問題はdictの理解ではなく、その中にネストされたリストの理解です。毎回同じキーを繰り返し処理しています。この種のことは、セットを使用した方が適切です。

s1 = set(l1)
d2 = {k: list(s1.intersection(v)) for k, v in d1.items()}
于 2012-08-10T14:11:43.480 に答える
1
l1 = ['cat', 'dog', 'mouse', 'horse', 'elephant', 
      'zebra', 'lion', 'snake', 'fly']

d1 = {'1':['dog', 'mouse', 'horse','orange', 'lemon'],
      '2':['apple', 'pear','cat', 'mouse', 'horse'], 
      '3':['kiwi', 'lime','cat', 'dog', 'mouse'], 
      '4':['carrot','potato','cat', 'dog', 'horse'], 
      '5':['chair', 'table', 'knife']}

def gen_items(valid_name_set, d):
    for k, v in d.iteritems():
        intersection = valid_name_set.intersection(v)
        if intersection: # not empty
            yield (k, intersection)

print dict(gen_items(set(l1), d1))

出力:

{'1': set(['dog', 'horse', 'mouse']),
 '2': set(['cat', 'horse', 'mouse']),
 '3': set(['cat', 'dog', 'mouse']),
 '4': set(['cat', 'dog', 'horse'])}

または:

from itertools import ifilter
from operator import itemgetter
set_l1 = set(l1)
d2 = dict(ifilter(itemgetter(1), 
                  ((k, set_l1.intersection(v)) for k, v in d1.iteritems())))
于 2012-08-10T14:27:56.200 に答える
0

使用set

>>> l1 = ['cat', 'dog', 'mouse', 'horse', 'elephant',
      'zebra', 'lion', 'snake', 'fly']
>>> d1 = {'1':['dog', 'mouse', 'horse','orange', 'lemon'],
      '2':['apple', 'pear','cat', 'mouse', 'horse'],
      '3':['kiwi', 'lime','cat', 'dog', 'mouse'],
      '4':['carrot','potato','cat', 'dog', 'horse'],
      '5':['chair', 'table', 'knife']}
>>> l1_set = set(l1)
>>> d2 = dict((k, set(d1[k]) & l1_set) for k in d1.keys())
>>> d2
{'1': set(['horse', 'mouse', 'dog']), '3': set(['mouse', 'dog', 'cat']), '2': set(['horse', 'mouse', 'cat']), '5': set([]), '4': set(['horse', 'dog', 'cat'])}
>>> d2 = dict((k, v) for k,v in d2.iteritems() if v)
>>> d2
{'1': set(['horse', 'mouse', 'dog']), '3': set(['mouse', 'dog', 'cat']), '2': set(['horse', 'mouse', 'cat']), '4': set(['horse', 'dog', 'cat'])}
于 2012-08-10T14:12:34.353 に答える
0

aに変換l1set、dictの理解をわずかに変更すると、これを約3倍速く動作させることができます。

l1 = set(['cat', 'dog', 'mouse', 'horse', 'elephant', 
      'zebra', 'lion', 'snake', 'fly'])

d1 = {'1':['dog', 'mouse', 'horse','orange', 'lemon'],
      '2':['apple', 'pear','cat', 'mouse', 'horse'], 
      '3':['kiwi', 'lime','cat', 'dog', 'mouse'], 
      '4':['carrot','potato','cat', 'dog', 'horse'], 
      '5':['chair', 'table', 'knife']}

d2 = {k: [a for a in d1[k] if a in l1] for k in d1.keys()}
print(d2)

パフォーマンスのベンチマークを行う方法は次のとおりです。

import timeit

t = timeit.Timer(
    "d2 = {k: [a for a in l1 if a in d1[k]] for k in d1.keys()}",
    "from __main__ import (d1, l1)",
    )
print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)

t = timeit.Timer(
    'd2 = {k: [a for a in d1[k] if a in l1] for k in d1.keys()}',
    "from __main__ import (d1, l1)",
    )
print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)

d1ここでは、を制御することはできず、フィルタリングの前にのすべての値をセットに変換するd1のは遅すぎると想定しています。

于 2012-08-10T14:17:41.350 に答える