1

I am trying to devise a logic in python for the given scenario - I have a list of multiple dictionaries, my main goal is to get the unique list of dictionary based on the id key.

non_unique = [
    {"id": 1, "name": "A", "items": ["blah1"]},
    {"id": 1, "name": "A", "items": ["blah2"]}
]

I can get the unique list of dictionaries by this dictionary comprehension:

list({v["id"]: v for v in non_unique}.values())

But I am unable to fit a logic in the dictionary comprehension to concatenate the value of items key. My expected output is:

[{"id": 1, "name": "A", "items": ["blah1", "blah2"]}]
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • What if `name` is different in two dictionaries with the same `id`? – mkrieger1 May 06 '20 at 09:23
  • Did you try writing a simple `for` loop? – mkrieger1 May 06 '20 at 09:26
  • Does this answer your question? [list to dictionary conversion with multiple values per key?](https://stackoverflow.com/questions/5378231/list-to-dictionary-conversion-with-multiple-values-per-key) – mkrieger1 May 06 '20 at 09:28
  • Why not a simple for loop as @mkrieger1 suggests ? – jossefaz May 06 '20 at 09:41
  • @mkrieger1 I need to concatenate only for a specific key whose value is a list type, in this case, `items`, I will give it a shot with loop. I was thinking if I will be able to modify the dictionary comprehension itself to output the desired result. – Shivam Srivastava May 06 '20 at 10:08

2 Answers2

1

Sometimes a simple for loop is much more clear than dict or list comprehension....in your case i would simple use :

from operator import itemgetter

non_unique = [{'id': 1, "name": "A", "items": ["blah1"]},
              {'id': 1, "name": "A", "items": ["blah2"]},
              {'id': 2, "name": "A", "items": ["blah2"]},
              {'id': 2, "name": "B", "items": ["blah1"]},
              ]
result = {}
for uniq in non_unique:
    id, items, name = itemgetter('id', 'items', 'name')(uniq)
    if id in result:
        result[id]["items"] += items
        if name not in result[id]["name"].split():
            result[id]["name"] += ",{}".format(name)
    else:
        result[id] = uniq

unique_list = [val for item, val in result.items()]
print(unique_list)

Output :

[{'id': 1, 'name': 'A', 'items': ['blah1', 'blah2']}, {'id': 2, 'name': 'A,B', 'items': ['blah2', 'blah1']}]

EDIT

As suggested in comments : i add a simple check for the name and add it to names if it does not exists.... I also add the itemgetter for getting a more "clear" code.

jossefaz
  • 3,312
  • 4
  • 17
  • 40
  • What if `id` 1 has different names? – Mayur Fartade May 06 '20 at 10:16
  • 1
    @Mayur Fartade : totally agree with you. This is why i said that it is based on the id and not on the name value. I just follow the question's author check which was on the id value. If he wants to check the name, he just has to add another check in the loop – jossefaz May 06 '20 at 10:28
  • 1
    @Mayur Fartade : I add this check as you seggested and add an EDIT note for that – jossefaz May 06 '20 at 10:43
0

You can use this method.

non_unique = [
    {'id': 1, 'name': "A", 'items': ["blah1"]},
    {'id': 1, 'name': "A", 'items': ["blah2"]}
]
dic = []
for v in non_unique:
    for x in dic:
        if x['id'] == v['id']:
            if v['name']not in x['name']:
                x['name'] += v['name']
            if v['items'] not in x['items']:
                x['items'] += v['items']
            break
    else:
        dic.append(v)
print(dic)

Output - [{'id': 1, 'name': 'A', 'items': ['blah1', 'blah2']}]

Mayur Fartade
  • 317
  • 3
  • 18