Сравнение диктов и обновление списка результатов - PullRequest
1 голос
/ 05 мая 2010

У меня есть список диктов, и я хочу сравнить каждый диктат в этом списке с диктом в результирующем списке, добавить его в список результатов, если его там нет, и, если он там, обновить счетчик, связанный с этим диктатом .

Сначала я хотел использовать решение, описанное в Python: список диктов, если существует, увеличивать значение диктов, если нет, добавлять новый дикт , но я получил ошибку, когда один дикт нельзя использовать как ключ к другому диктату.

Таким образом, структура данных, которую я выбрал, представляет собой список, в котором каждая запись является dict и int:

r = [[{'src': '', 'dst': '', 'cmd': ''}, 0]]

Исходный набор данных (который следует сравнить с результирующим набором данных) представляет собой список диктов:

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]]

Каков лучший способ сделать это? У меня есть несколько примеров кода, но ни один из них не очень хорош, и большинство из них работает неправильно.

Спасибо за любой вклад в это!

UPDATE

Окончательный код после комментариев Тамоса:

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))

Ответы [ 2 ]

1 голос
/ 05 мая 2010

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])
1 голос
/ 05 мая 2010

Что ж, если ваши исходные дикты содержат только src, dst и cmd, вы можете вместо этого использовать именованные кортежи, которые можно хэшировать, поэтому вы можете использовать именованные кортежи в диктовке в качестве ключей.

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 экземпляров из диктов:

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, здесь есть вставной <code>namedtuple класс замены здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...