У меня есть список dicts, и я хочу сравнить каждый dict в том списке с dict в получающемся списке, добавить, что он к результату перечисляет, если это не там, и если это там, обновите счетчик, связанный с этим dict.
Сначала я хотел использовать решение, описанное в Python: Список dict, если существует инкремент значение dict, если не добавляют новый dict, но я получил ошибку, где один dict не может использоваться в качестве ключа к другому dict.
Таким образом, структура данных, которую я выбрал, является списком, где каждая запись является dict и интервалом:
r = [[{'src': '', 'dst': '', 'cmd': ''}, 0]]
Исходный набор данных (который должен сравниться с получающимся набором данных) является списком dicts:
d1 = {'src': '192.168.0.1',
'dst': '192.168.0.2',
'cmd': 'cmd1'}
d2 = {'src': '192.168.0.1',
'dst': '192.168.0.2',
'cmd': 'cmd2'}
d3 = {'src': '192.168.0.2',
'dst': '192.168.0.1',
'cmd': 'cmd1'}
d4 = {'src': '192.168.0.1',
'dst': '192.168.0.2',
'cmd': 'cmd1'}
o = [d1, d2, d3, d4]
Результат должен быть:
r = [[{'src': '192.168.0.1', 'dst': '192.168.0.2', 'cmd': 'cmd1'}, 2],
[{'src': '192.168.0.1', 'dst': '192.168.0.2', 'cmd': 'cmd2'}, 1],
[{'src': '192.168.0.2', 'dst': '192.168.0.1', 'cmd': 'cmd1'}, 1]]
Что лучший способ состоит в том, чтобы выполнить это? У меня есть несколько примеров кода, но ни один не действительно хорош, и большинство не работает правильно.
Спасибо за любой вход на этом!
ОБНОВЛЕНИЕ
Заключительный код после Tamås комментирует:
from collections import namedtuple, defaultdict
DataClass = namedtuple("DataClass", "src dst cmd")
d1 = DataClass(src='192.168.0.1', dst='192.168.0.2', cmd='cmd1')
d2 = DataClass(src='192.168.0.1', dst='192.168.0.2', cmd='cmd2')
d3 = DataClass(src='192.168.0.2', dst='192.168.0.1', cmd='cmd1')
d4 = DataClass(src='192.168.0.1', dst='192.168.0.2', cmd='cmd1')
ds = d1, d2, d3, d4
r = defaultdict(int)
for d in ds:
r[d] += 1
print "list to compare"
for d in ds:
print d
print "result after merge"
for k, v in r.iteritems():
print("%s: %s" % (k, v))
Что ж, если ваши исходные dicts содержат только src
, dst
и cmd
, вместо этого вы можете использовать именованные кортежи, которые можно хэшировать, поэтому вы можете использовать именованные кортежи в dict в качестве ключей.
from collections import namedtuple
DataClass = namedtuple("DataClass", "src dst cmd")
d1 = DataClass(src='192.168.0.2', dst='192.168.0.1', cmd='cmd1')
(Извините за глупое название класса; поскольку я не знаю, что представляют собой ваши диктовки, я не мог придумать лучшего имени). Вы даже можете создать экземпляры DataClass
из dicts:
d1 = DataClass(**d1_as_dict)
На этом этапе ваш основной цикл подсчета упрощается до следующего:
from collections import defaultdict, namedtuple
r = defaultdict(int)
for obj in [d1, d2, d3, d4]:
r[obj] += 1
Если по какой-то причине вы застряли на Python <= 2.5, существует подключаемый namedtuple
класс замены здесь .
namedtuple
- отличная идея, если она применима. Но если вы хотите использовать dict
s, это, конечно, тоже возможно, просто значительно менее эффективно. Например:
def addadict(r, newd):
for i, (d, count) in enumerate(r):
if d == newd:
r[i] = [d, count+1]
break
else:
r.append([newd, 1])