user875139
user875139

Reputation: 1621

Way to detect duplicate key values in a dict array in python?

Given the code below:

a = [{"name": "Sport"}, {"name": "Games"}, {"name": "Videos"}, {"name": "Sport"}]

How can I find out if another dict in the a variable has the same name value? In the example above, the result should return "Sport".

Thanks in advance.

Upvotes: 1

Views: 1718

Answers (4)

Stefan Pochmann
Stefan Pochmann

Reputation: 28606

A couple more ways:

>>> seen = set()
>>> {n for n in (d['name'] for d in a) if n in seen or seen.add(n)}
{'Sport'}

>>> seen = set()
>>> {n for d in a for n in [d['name']] if n in seen or seen.add(n)}
{'Sport'}

>>> k, seen = 'name', set()
>>> {d[k] for d in a if d[k] in seen or seen.add(d[k])}
{'Sport'}

>>> seen = {}
>>> {d['name'] for i, d in enumerate(a) if seen.setdefault(d['name'], i) != i}
{'Sport'}

>>> seen = {}
>>> {d['name'] for d in a if seen.setdefault(d['name'], id(d)) != id(d)}
{'Sport'}

>>> x = set(), set()
>>> for n in (d['name'] for d in a): x[n in x[0]].add(n)
>>> x[1]
{'Sport'}

Upvotes: 2

Shashank
Shashank

Reputation: 13869

Sets are a useful data structure to use here because they have constant time insertion and containment tests, unlike lists.

def first_duplicate_name(dictlist):
    seen = set()
    seen_add = seen.add
    for dct in dictlist:
        k = dct['name']
        if k in seen: # constant time AKA O(1)
            return k
        else:
            seen_add(k) # also O(1)

Upvotes: 0

Óscar López
Óscar López

Reputation: 236004

This builds on @AdamSmith's answer, but is a bit shorter thanks to the use of list comprehensions:

from collections import Counter

a = [{"name": "Sport"}, {"name": "Games"}, {"name": "Videos"}, {"name": "Sport"}]
[name for name, count in Counter(x['name'] for x in a).items() if count > 1]

As a result we'll get a list of the duplicates:

['Sport']

Upvotes: 2

Adam Smith
Adam Smith

Reputation: 54213

Lots of great ways to do it. The canonical one in Python is probably to use a collections.Counter

from collections import Counter

c = Counter([d['name'] for d in a])
for value,count in c.items():
    if count > 1:
        print(value)

If all you need to know is whether or not something is a duplicate (not how many times it has been duplicated), you can simplify by just using a seen set.

seen = set()
for d in a:
    val = d['name']
    if val in seen:
        print(val)
    seen.add(val)

Probably the most over-engineered way to do it would be to sort the dicts by their "name" value, then run a groupby and check each group's length.

from itertools import groupby
from operator import itemgetter

namegetter = itemgetter('name')

new_a = sorted(a, key=namegetter)

groups = groupby(new_a, namegetter)

for groupname, dicts in groups:
    if len(list(dicts)) > 1:
        print(groupname)

Upvotes: 9

Related Questions