32

2 つの異なる辞書で対応するキーを見つけようとしています。それぞれに約 600k のエントリがあります。

たとえば、次のように言います。

    myRDP = { 'Actinobacter': 'GATCGA...TCA', 'subtilus sp.': 'ATCGATT...ACT' }
    myNames = { 'Actinobacter': '8924342' }

myRDP の値と一致するため、Actinobacter (8924342) の値を出力したいと思います。

次のコードは機能しますが、非常に遅いです。

    for key in myRDP:
        for jey in myNames:
            if key == jey:
                print key, myNames[key]

次のことを試しましたが、常に KeyError が発生します。

    for key in myRDP:
        print myNames[key]

これを行うためにCで実装された機能はおそらくありますか?私は周りをグーグルで検索しましたが、何も機能していないようです。

ありがとう。

4

11 に答える 11

50

intersectionセットを使用します。これらには、迅速なメソッドが組み込まれているためです。

myRDP = { 'Actinobacter': 'GATCGA...TCA', 'subtilus sp.': 'ATCGATT...ACT' }
myNames = { 'Actinobacter': '8924342' }

rdpSet = set(myRDP)
namesSet = set(myNames)

for name in rdpSet.intersection(namesSet):
    print name, myNames[name]

# Prints: Actinobacter 8924342
于 2009-08-23T00:32:07.080 に答える
48

あなたはこれを行うことができます:

for key in myRDP:
    if key in myNames:
        print key, myNames[key]

myRDP のすべてのキーと myNames のすべてのキーを比較していたため、最初の試行は遅かったです。アルゴリズムの専門用語で、myRDP にn 個の要素があり、myNames にm個の要素がある場合、そのアルゴリズムは O( n × m ) 操作を行います。それぞれ 60 万要素の場合、これは 360,000,000,000 回の比較になります。

しかし、特定の要素がディクショナリのキーであるかどうかのテストは高速です。実際、これはディクショナリの特徴の 1 つです。アルゴリズム用語では、key in dictテストは O(1)、つまり一定時間です。したがって、私のアルゴリズムは O( n ) 時間かかります。これは 600,000 分の 1 です。

于 2009-08-23T00:30:01.247 に答える
9
for key in myRDP:
    name = myNames.get(key, None)
    if name:
        print key, name

dict.getNoneキーが存在しない場合は、指定したデフォルト値 (この場合は ) を返します。

于 2009-08-23T00:30:47.813 に答える
7

共通キーを見つけることから始めて、それらを反復することができます。集合演算は、少なくとも最新バージョンの Python では C で実装されているため、高速である必要があります。

common_keys = set(myRDP).intersection(myNames)
for key in common_keys:
    print key, myNames[key]
于 2009-08-23T00:34:51.217 に答える
2

get代わりに次のメソッドを使用してください。

 for key in myRDP:
    value = myNames.get(key)
    if value != None:
      print key, "=", value
于 2009-08-23T00:31:06.597 に答える
2

最善かつ最も簡単な方法は、一般的なセット操作 (Python 3) を実行することです。

a = {"a": 1, "b":2, "c":3, "d":4}
b = {"t1": 1, "b":2, "e":5, "c":3}
res = a.items() & b.items() # {('b', 2), ('c', 3)} For common Key and Value
res = {i[0]:i[1] for i in res}  # In dict format
common_keys = a.keys() & b.keys()  # {'b', 'c'}

乾杯!

于 2019-05-31T16:25:48.503 に答える
0

辞書で交差、結合、相違、およびその他のセット操作を実行するための私のコードは次のとおりです。

class DictDiffer(object):
    """
    Calculate the difference between two dictionaries as:
    (1) items added
    (2) items removed
    (3) keys same in both but changed values
    (4) keys same in both and unchanged values
    """
    def __init__(self, current_dict, past_dict):
        self.current_dict, self.past_dict = current_dict, past_dict
        self.set_current, self.set_past = set(current_dict.keys()), set(past_dict.keys())
        self.intersect = self.set_current.intersection(self.set_past)
    def added(self):
        return self.set_current - self.intersect 
    def removed(self):
        return self.set_past - self.intersect 
    def changed(self):
        return set(o for o in self.intersect if self.past_dict[o] != self.current_dict[o])
    def unchanged(self):
        return set(o for o in self.intersect if self.past_dict[o] == self.current_dict[o])

if __name__ == '__main__':
    import unittest
    class TestDictDifferNoChanged(unittest.TestCase):
        def setUp(self):
            self.past = dict((k, 2*k) for k in range(5))
            self.current = dict((k, 2*k) for k in range(3,8))
            self.d = DictDiffer(self.current, self.past)
        def testAdded(self):
            self.assertEqual(self.d.added(), set((5,6,7)))
        def testRemoved(self):      
            self.assertEqual(self.d.removed(), set((0,1,2)))
        def testChanged(self):
            self.assertEqual(self.d.changed(), set())
        def testUnchanged(self):
            self.assertEqual(self.d.unchanged(), set((3,4)))
    class TestDictDifferNoCUnchanged(unittest.TestCase):
        def setUp(self):
            self.past = dict((k, 2*k) for k in range(5))
            self.current = dict((k, 2*k+1) for k in range(3,8))
            self.d = DictDiffer(self.current, self.past)
        def testAdded(self):
            self.assertEqual(self.d.added(), set((5,6,7)))
        def testRemoved(self):      
            self.assertEqual(self.d.removed(), set((0,1,2)))
        def testChanged(self):
            self.assertEqual(self.d.changed(), set((3,4)))
        def testUnchanged(self):
            self.assertEqual(self.d.unchanged(), set())
    unittest.main()
于 2009-08-23T02:24:02.163 に答える
0

両方の辞書を1 つの辞書/配列にコピーします。1:1 の関連値があるため、これは理にかなっています。次に、1 つの検索のみが必要で、比較ループは不要で、関連する値に直接アクセスできます。

結果のディクショナリ/配列の例:

[Name][Value1][Value2]

[Actinobacter][GATCGA...TCA][8924342]

[XYZbacter][BCABCA...ABC][43594344]

...

于 2009-08-23T00:31:43.493 に答える