Reputation: 407
I have a list of dicts like this:
dicts = [
{ "name": "user1", "group": "group1" },
{ "name": "user2", "group": "group2" },
{ "name": "user3", "group": "group1" },
{ "name": "user3", "group": "group3" }
]
and I would like to group its elements by their names and create a tuple of the possible groups like:
groupped_dicts = [
{ "name": "user1", "group": "group1" },
{ "name": "user2", "group": "group2" },
{ "name": "user3", "group": ("group1","group3") }
]
What I have tried looks like this:
from itertools import groupby
from operator import itemgetter
dicts = sorted(dicts, key=itemgetter('name'))
result = [{
'username': key,
'group': "','".join(item['value'] for item in group)
} for key, group in itertools.groupby(dicts, key=itemgetter('name'))]
Could you help me achieve this?
Upvotes: 0
Views: 105
Reputation: 12107
With small change to output structure:
grouped_dicts = {'user1': ['group1'], 'user2': ['group2'], 'user3': ['group1', 'group3']}
You can do it like:
grouped_dicts = {}
for d in dicts:
if d['name'] not in grouped_dicts:
grouped_dicts[d['name']] = []
grouped_dicts[d['name']].append(d['group'])
Upvotes: 1
Reputation: 26946
Although not getting you exactly to your expected output if you were to replace the string join with a comprehension, this would get you to a much closer result:
from itertools import groupby
from operator import itemgetter
dicts = sorted(dicts, key=itemgetter('name'))
result = [{
'username': key,
'group': tuple(item['group'] for item in group)
} for key, group in groupby(dicts, key=itemgetter('name'))]
result
# [{'username': 'user1', 'group': ('group1',)},
# {'username': 'user2', 'group': ('group2',)},
# {'username': 'user3', 'group': ('group1', 'group3')}]
However, I would find this an improper use of these data structures.
This data would be served much better by a dict
:
result = {}
for d in dicts:
name = d['name']
group = d['group']
if name not in result:
result[name] = []
result[name].append(group)
print(result)
# {'user1': ['group1'], 'user2': ['group2'], 'user3': ['group1', 'group3']}
which can be later easily converted to what you are after
[{"name": name, "group": tuple(groups) if len(groups) != 1 else groups[0]} for name, groups in result.items()]
# [{'name': 'user1', 'group': 'group1'},
# {'name': 'user2', 'group': 'group2'},
# {'name': 'user3', 'group': ('group1', 'group3')}]
Upvotes: 1