Graddy
Graddy

Reputation: 3008

Number of different values assoicated with a key in a list of dicts

Given a list of dictionaries ( each of which have same keys), I want total number of different values with which a given key is associated

$ li = [{1:2,2:3},{1:2,2:4}] $ the expected output is {1:1,2:2}

I came up with the following piece of code...Is there a better way of doing this ?

      counts = {} 
      values = {}
      for i in li:  
         for key,item in i.items():
             try:
                 if item in values[key]:
                    continue
             except KeyError:
                 else:
                    try:
                       counts[key] += 1
                    except KeyError:
                       counts[key] = 1
                    try:
                       values[key].append(item)
                    except KeyError:
                       values[key] = [item]

Upvotes: 0

Views: 116

Answers (5)

fransua
fransua

Reputation: 1608

using flattening list in case dicts are not alway same length:

li=[{1: 2, 2: 3}, {1: 2, 2: 4}, {1: 3}]
dic={}
for i,j in [item for sublist in li for item in sublist.items()]:
    dic[i] = dic[i]+1 if i in dic else 1

Upvotes: 0

Andrew Clark
Andrew Clark

Reputation: 208475

Here is yet another alternative:

from collections import defaultdict

counts = defaultdict(int)
for k, v in set(pair for d in li for pair in d.items()):
    counts[k] += 1

And the result:

>>> counts
defaultdict(<type 'int'>, {1: 1, 2: 2})

Upvotes: 1

g.d.d.c
g.d.d.c

Reputation: 47988

Something like this is probably more direct:

from collections import defaultdict

counts = defaultdict(set)

for mydict in li:
  for k, v in mydict.items():
    counts[k].add(v)

That takes care of the collecting / counting of the values. To display them like you want them, this would get you there:

print dict((k, len(v)) for k, v in counts.items())
# prints {1: 1, 2: 2}

Upvotes: 4

yurib
yurib

Reputation: 8147

counts = {} 
values = {}

for i in li:  
  for key,item in i.items():
    if not (key in values.keys()):
      values[key] = set()
    values[key].add(item)

for key in values.keys():
  counts[key] = len(values[key])

Upvotes: 0

srgerg
srgerg

Reputation: 19329

You could so something like this:

li = [{1:2,2:3},{1:2,2:4}]

def makesets(x, y):
  for k, v in x.iteritems():
    v.add(y[k])
  return x

distinctValues = reduce(makesets, li, dict((k, set()) for k in li[0].keys()))
counts = dict((k, len(v)) for k, v in distinctValues.iteritems())
print counts

When I run this it prints:

{1: 1, 2: 2}

which is the desired result.

Upvotes: 0

Related Questions