Поиск совпадающих ключей в двух больших словарях и быстрое выполнение
Я пытаюсь найти соответствующие ключи в двух разных словарях. Каждый из них имеет около 600 тыс. Записей.
Скажите, например:
myRDP = { 'Actinobacter': 'GATCGA...TCA', 'subtilus sp.': 'ATCGATT...ACT' }
myNames = { 'Actinobacter': '8924342' }
Я хочу распечатать значение для Actinobacter (8924342), так как оно соответствует значению в myRDP.
Следующий код работает, но очень медленный:
for key in myRDP:
for jey in myNames:
if key == jey:
print key, myNames[key]
Я пробовал следующее, но всегда имеет значение KeyError:
for key in myRDP:
print myNames[key]
Возможно, существует функция, реализованная в C для этого? Я искал googled, но ничего не работает.
Спасибо.
Ответы
Ответ 1
Используйте наборы, потому что у них есть встроенный метод 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
Ответ 2
Вы можете сделать это:
for key in myRDP:
if key in myNames:
print key, myNames[key]
Ваша первая попытка была медленной, потому что вы сравнивали каждый ключ в myRDP с каждым ключом в myNames. В алгоритмическом жаргоне, если myRDP имеет n, а myNames имеет m элементы, тогда этот алгоритм будет принимать O (n × m). Для 600 тыс. Элементов каждый из них составляет 360 000 000 000 сравнений!
Но проверка того, является ли конкретный элемент ключом словаря быстрым - на самом деле, это одна из определяющих характеристик словарей. В алгоритмических терминах тест key in dict
равен O (1) или постоянному времени. Таким образом, мой алгоритм будет принимать время O (n), что составляет 600 000-й раз.
Ответ 3
for key in myRDP:
name = myNames.get(key, None)
if name:
print key, name
dict.get
возвращает значение по умолчанию, которое вы ему даете (в данном случае None
), если ключ не существует.
Ответ 4
Вы можете начать с поиска общих ключей, а затем итерации по ним. Операции Set должны быть быстрыми, потому что они реализованы на C, по крайней мере, в современных версиях Python.
common_keys = set(myRDP).intersection(myNames)
for key in common_keys:
print key, myNames[key]
Ответ 5
в python 3 вы можете просто сделать
myNames.keys() & myRDP.keys()
Ответ 6
Вместо этого используйте get
:
for key in myRDP:
value = myNames.get(key)
if value != None:
print key, "=", value
Ответ 7
Скопируйте оба словаря в словарь один. Это имеет смысл, поскольку у вас есть связанные 1:1 значения. Затем вам нужен только один поиск, отсутствие цикла сравнения и прямой доступ к связанному значению.
Пример Результат Словарь/Массив:
[Name][Value1][Value2]
[Actinobacter][GATCGA...TCA][8924342]
[XYZbacter][BCABCA...ABC][43594344]
код >
...
Ответ 8
Вот мой код для выполнения пересечений, союзов, различий и других заданий на словарях:
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()