关于python:比较dicts并更新结果列表

Comparing dicts and update a list of result

我有一个口述列表,我想将列表中的每个口述与结果列表中的一个口述进行比较,如果不在结果列表中,则将其添加到结果列表中;如果在结果列表中,则更新与该口述关联的计数器。

首先,我想使用python:list of dict中描述的解决方案,如果存在,则递增dict值,如果不附加新的dict,但我得到了一个错误,其中一个dict不能用作另一个dict的键。

所以我选择的数据结构是一个列表,其中每个条目都是一个dict和一个int:

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

原始数据集(应与结果数据集进行比较)是一个dict列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
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]

结果应该是:

1
2
3
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注释是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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))


如果适用,namedtuple是一个很好的主意。但是如果你想坚持使用dict,那当然也是可能的,只是效率要低得多。例如:

1
2
3
4
5
6
7
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])


好吧,如果您的原始dict只包含srcdstcmd,那么您可以使用可散列的命名元组,这样您就可以在dict中使用命名元组作为键。

1
2
3
4
from collections import namedtuple

DataClass = namedtuple("DataClass","src dst cmd")
d1 = DataClass(src='192.168.0.2', dst='192.168.0.1', cmd='cmd1')

(对不起这个愚蠢的班级名称,因为我不知道你的听写代表什么,所以我想不出一个更好的名字)。您甚至可以从dicts创建DataClass实例:

1
d1 = DataClass(**d1_as_dict)

此时,您的主计数循环简化为:

1
2
3
4
5
from collections import defaultdict, namedtuple

r = defaultdict(int)
for obj in [d1, d2, d3, d4]:
    r[obj] += 1

如果出于某种原因,您坚持使用python<=2.5,那么这里的namedtuple替换类会有所下降。