Create dict (key: list of objects) from list of objects using value of object as key

Question:

I have the following list of objects (simplified)

where object is a class

from dataclasses import @dataclass

@dataclass
class LinkObject:
    id: int
    link_id: int
    name: str


list_of_obs = [
    LinkObject(1, 2, 'a'),
    LinkObject(2, 2, 'b'),
    LinkObject(3, 3, 'c'),
    LinkObject(4, 3, 'd'),
]

I would like to convert the above into the following dict (key is link_id in object above: –

{
    2: [
        LinkObject(id=1, link_id=2, name='a'),
        LinkObject(id=2, link_id=2, name='b'),
    ], 
    3: [
        LinkObject(id=3, link_id=3, name='c'),
        LinkObject(id=4, link_id=3, name='d'),
    ]
}

What is the correct way to do this using comprehension?

Ive tried : –

a_dict = {i.link_id: [i] for i in list_of_obs}

which is incorrect.

Thanks

Asked By: dsg

||

Answers:

Dictionary values should be accessed via square bracket notation:

i['link_id']

To actually put divide the list of objects into groups, you would need a loop or you can use the itertools package.

Using loop:

d = {}
for i in list_of_obs:
    # get the existing list for link_id, or create a new list for the link_id if not seen before
    lst = d.get(i['link_id'], [])
    lst.append(i)
    d[i['link_id']] = lst

Using itertools:
one caveat is that you need to sort the list_of_obs by 'link_id' for groupby to work correctly.

from itertools import groupby
list_of_obs_sorted = sorted(list_of_obs, key=lambda i: i['link_id'])
d = {name: list(group) for name, group in groupby(list_of_obs_sorted, key=lambda i: i['link_id'])}
Answered By: Tim

You can do this with a couple of nested comprehensions:

obs_by_link_id = {
    link_id: [o for o in list_of_obs if o['link_id'] == link_id]
    for link_id in {o['link_id'] for o in list_of_obs}
}

which gives you:

obs_by_link_id == {
    2: [
        {'id': 1, 'link_id': 2, 'name': 'a'},
        {'id': 2, 'link_id': 2, 'name': 'b'}
    ],
    3: [
        {'id': 3, 'link_id': 3, 'name': 'c'},
        {'id': 4, 'link_id': 3, 'name': 'd'}
    ]
}
Answered By: Samwise
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.