views:

129

answers:

6

I'm trying to count up ip addresses found in a log file on two servers and then merge the dictionary stats together without loosing elements or counts. I found a partial solution in another stack overflow question but as you can see it drops the '10.10.0.1':7 pair.

>>> a = {'192.168.1.21':23,'127.0.0.1':5,'12.12.12.12':5,'55.55.55.55':10}
>>> b = {'192.168.1.21':27,'10.10.0.1':7,'127.0.0.1':1}
>>> c = {}
>>> for elem in a:
...     c[elem] = b.get(elem, 0) + a[elem]
...
>>> print c
{'55.55.55.55': 10, '12.12.12.12': 5, '127.0.0.1': 6, '192.168.1.21': 50}

The counts are being added together but if the key doesn't exist in dict a, it gets dropped. I'm having trouble figuring out the last bit of logic... perhaps another for elem in b: if a.get(elem, 0) exists: pass else add it to c?

+4  A: 

If you have Python 2.7+, try collections.Counter

Otherwise try the following:

a = {'192.168.1.21':23,'127.0.0.1':5,'12.12.12.12':5,'55.55.55.55':10}
b = {'192.168.1.21':27,'10.10.0.1':7,'127.0.0.1':1}
c = {}
for dictionary in (a,b):
    for k,v in dictionary.iteritems():
        c[k] = c.get(k, 0) + v
eumiro
I'm on redhat enterprize server 4 server so I have python 2.3.4 : (
foxhop
Does the alternative solution work for you?
eumiro
+2  A: 

How about:

c = dict((k, a.get(k, 0) + b.get(k, 0)) for k in set(a.keys() + b.keys()))
llasram
+3  A: 
>>> from collections import Counter
>>> a = {'192.168.1.21':23,'127.0.0.1':5,'12.12.12.12':5,'55.55.55.55':10}
>>> b = {'192.168.1.21':27,'10.10.0.1':7,'127.0.0.1':1}
>>> dict(Counter(a) + Counter(b))
{'55.55.55.55': 10, '10.10.0.1': 7, '12.12.12.12': 5, '127.0.0.1': 6, '192.168.1.21': 50}
DisplacedAussie
+1 I like this.
hughdbrown
`Counter` is a `dict`
SilentGhost
+5  A: 

In your code replace c = {} with c = b.copy()

vartec
Thank you, this resolved my issue quickest.
foxhop
+1  A: 

This should be a pretty generic answer to your question, if I got it.

def merge_sum_dictionaries(*dicts):
    result_dict = {}
    for d in dicts:
        for key, value in d.iteritems():
            result_dict.setdefault(key, 0)
            result_dict[key] += value
    return result_dict



if __name__ == "__main__":
    a = {'192.168.1.21':23,'127.0.0.1':5,'12.12.12.12':5,'55.55.55.55':10}
    b = {'192.168.1.21':27,'10.10.0.1':7,'127.0.0.1':1}

    print merge_sum_dictionaries(a, b)

Output:

{'55.55.55.55': 10, '10.10.0.1': 7, '12.12.12.12': 5, '127.0.0.1': 6, '192.168.1.21': 50}
Alan Franzoni
+1  A: 

Solution for python 2.6 and higher:

from collections import defaultdict

def merge_count_dicts(*dicts):
    result = defaultdict(int)
    for d in dicts:
        for k, v in d.items():
            result[k] += v
    return result

def test():
    a = {'192.168.1.21':23,'127.0.0.1':5,'12.12.12.12':5,'55.55.55.55':10}
    b = {'192.168.1.21':27,'10.10.0.1':7,'127.0.0.1':1}
    c = merge_count_dicts(a, b)
    print c

if __name__ == '__main_':
    test()
hughdbrown
That's the other way to setdefault() :P
Alan Franzoni
OP's using python-2.3
SilentGhost
@SG: just saw that...
hughdbrown