Domanda

Sto cercando di trovare le chiavi corrispondenti a due diversi dizionari. Ognuno ha circa 600k voci.

Diciamo per esempio:

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

Voglio stampare il rapporto qualità-Actinobacter (8.924.342), in quanto corrisponde a un valore in myRDP.

Il seguente codice funziona, ma è molto lento:

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

Ho provato quanto segue ma si traduce sempre in un KeyError:

    for key in myRDP:
        print myNames[key]

C'è forse una funzione implementata in C per fare questo? Googled intorno ma nulla sembra funzionare.

Grazie.

È stato utile?

Soluzione

Utilizzare set, perché hanno un built-in metodo intersection che dovrebbe essere rapido:

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

Altri suggerimenti

Si potrebbe fare questo:

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

Il primo tentativo è stato lento a causa di comparare ogni chiave in myRDP con ogni tasto in myNames. In gergo algoritmico, se myRDP ha n elementi e myNames ha m gli elementi, quindi che l'algoritmo avrebbe preso O ( n × m ) per le operazioni. Per 600k elementi ciascuno, questo è 360,000,000,000 paragoni!

Ma testare se un particolare elemento è una chiave di un dizionario è veloce - in realtà, questa è una delle caratteristiche distintive di dizionari. In termini algoritmici, il test key in dict è O (1), o tempo costante. Quindi il mio algoritmo prende O ( n ) il tempo, che è uno 600000e del tempo.

in Python 3 si può solo fare

myNames.keys() & myRDP.keys()

for key in myRDP:
    name = myNames.get(key, None)
    if name:
        print key, name

dict.get restituisce il valore di default si dà (in questo caso, None) se la chiave non esiste.

Si potrebbe iniziare trovando le chiavi comuni e poi iterare su di loro. Set operazioni devono essere veloci, perché sono implementate in C, almeno nelle versioni moderne di Python.

common_keys = set(myRDP).intersection(myNames)
for key in common_keys:
    print key, myNames[key]

Utilizzare il metodo get invece:

 for key in myRDP:
    value = myNames.get(key)
    if value != None:
      print key, "=", value

Best e modo più semplice sarebbe semplicemente eseguire le operazioni di set comune (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'}

Cheers!

Copia entrambi i dizionari in una dizionario / array. Questo ha senso quando si dispone di 1: 1 valori legati. Allora avete bisogno di una sola ricerca, nessun ciclo confronto, e si può accedere direttamente al relativo valore.

Esempio Con conseguente Dictionary / Array:

[Name][Value1][Value2]

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

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

...

Ecco il mio codice per fare le intersezioni, i sindacati, le differenze, e le altre operazioni di set on dizionari:

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()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top