How to extract two values from dict in python?

Question:

I’m using python3 and and i have data set. That contains the following data. I’m trying to get the desire value from this data list. I have tried many ways but unable to figure out how to do that.

slots_data = [
        {
            "id":551,
            "user_id":1,
            "time":"199322002",
            "expire":"199322002"
        },
        {
            "id":552,
            "user_id":1,
            "time":"199322002",
            "expire":"199322002"
        },
        {
            "id":525,
            "user_id":3,
            "time":"199322002",
            "expire":"199322002"
        },
        {
            "id":524,
            "user_id":3,
            "time":"199322002",
            "expire":"199322002"
        },
        {
            "id":553,
            "user_id":1,
            "time":"199322002",
            "expire":"199322002"
        },
         {
            "id":550,
            "user_id":2,
            "time":"199322002",
            "expire":"199322002"
        }
    ]
    
    
    # Desired output 
    # [
    # {"user_id":1,"slots_ids":[551,552,553]}
    # {"user_id":2,"slots_ids":[550]}
    # {"user_id":3,"slots_ids":[524,525]}
    # ]

I have tried in the following way and obviously this is not correct. I couldn’t figure out the solution of this problem :

final_list = []
for item in slots_data:
    obj = obj.dict()
    obj = {
    "user_id":item["user_id"],
    "slot_ids":item["id"]
    }

    final_list.append(obj)

print(set(final_list))
Asked By: Ahmed Yasin

||

Answers:

I would say try using pandas to group the user id’s together and convert it back to a dictionary

pd.DataFrame(slots_data).groupby('user_id')['id'].agg(list).reset_index().to_dict('records')

[{'user_id': 1, 'id': [551, 552, 553]},
 {'user_id': 2, 'id': [550]},
 {'user_id': 3, 'id': [525, 524]}]
Answered By: It_is_Chris

The other answer added here has a nice solution, but here’s one without using pandas:

users = {}
for item in slots_data:
    # Check if we've seen this user before,
    if item['user_id'] not in users:
        # if not, create a new entry for them
        users[item['user_id']] = {'user_id': item['user_id'], 'slot_ids': []}

    # Add their slot ID to their dictionary
    users[item['user_id']]['slot_ids'].append(item['id'])

# We only need the values (dicts)
output_list = list(users.values())
Answered By: Xiddoc

thriough just simple loop way

>>> result = {}
>>> for i in slots_data:
...     if i['user_id'] not in result:
...             result[i['user_id']] = []
...     result[i['user_id']].append(i['id'])
... 
>>> output = []
>>> for i in result:
...     dict_obj = dict(user_id=i, slots_id=result[i])
...     output.append(dict_obj)
... 
>>> output
[{'user_id': 1, 'slots_id': [551, 552, 553]}, {'user_id': 3, 'slots_id': [525, 524]}, {'user_id': 2, 'slots_id': [550]}]
Answered By: sahasrara62

This can be made in a using listcomprehension:

final_list = [{"user_id": user_id, "id":sorted([slot["id"] for slot in slots_data if slot["user_id"] == user_id])} for user_id in sorted(set([slot["user_id"] for slot in slots_data]))]

A more verbose and better formatted version of the same code:

all_user_ids = [slot["user_id"] for slot in slots_data]
unique_user_ids = sorted(set(all_user_ids))
final_list = [
    {
        "user_id": user_id,
        "id": sorted([slot["id"] for slot in slots_data if slot["user_id"] == user_id])
    }
    for user_id in unique_user_ids]

Explanation:

  1. get all the user ids with list comprehension
  2. get the unique user ids by creating a set
  3. create the final list of dictionaries using list comprehension.
  4. each field id is of itself a list with list comprehension. We get the id of the slot, and only add it to the list, if the user ids match
Answered By: Jeanot Zubler

You can use the following to get it done. Purely Python. Without any dependencies.

slots_data = [
        {
            "id":551,
            "user_id":1,
            "time":"199322002",
            "expire":"199322002"
        },
        {
            "id":552,
            "user_id":1,
            "time":"199322002",
            "expire":"199322002"
        },
        {
            "id":525,
            "user_id":3,
            "time":"199322002",
            "expire":"199322002"
        },
        {
            "id":524,
            "user_id":3,
            "time":"199322002",
            "expire":"199322002"
        },
        {
            "id":553,
            "user_id":1,
            "time":"199322002",
            "expire":"199322002"
        },
         {
            "id":550,
            "user_id":2,
            "time":"199322002",
            "expire":"199322002"
        }
    ]

user_wise_slots = {}
for slot_detail in slots_data:
    if not slot_detail["user_id"] in user_wise_slots:
        user_wise_slots[slot_detail["user_id"]] = {
            "user_id": slot_detail["user_id"],
            "slot_ids": []
        }
    user_wise_slots[slot_detail["user_id"]]["slot_ids"].append(slot_detail["id"])
print(user_wise_slots.values())
Answered By: Nishant Jain

Lots of good answers here.

If I was doing this, I would base my answer on setdefault and/or collections.defaultdict that can be used in a similar way. I think the defaultdict version is very readable but if you are not already importing collections you can do without it.

Given your data:

slots_data = [
    {
        "id":551,
        "user_id":1,
        "time":"199322002",
        "expire":"199322002"
    },
    {
        "id":552,
        "user_id":1,
        "time":"199322002",
        "expire":"199322002"
    },
    #....
]

You can reshape it into your desired output via:

## -------------------
## get the value for the key user_id if it exists
## if it does not, set the value for that key to a default
## use the value to append the current id to the sub-list
## -------------------
reshaped = {}
for slot in slots_data:
    user_id = slot["user_id"]
    id = slot["id"]
    reshaped.setdefault(user_id, []).append(id)
## -------------------
 
## -------------------
## take a second pass to finish the shaping in a sorted manner
## -------------------
reshaped = [
    {
        "user_id": user_id,
        "slots_ids": sorted(reshaped[user_id])
    }
    for user_id
    in sorted(reshaped)
]
## -------------------

print(reshaped)

That will give you:

[
   {'user_id': 1, 'slots_ids': [551, 552, 553]},
   {'user_id': 2, 'slots_ids': [550]},
   {'user_id': 3, 'slots_ids': [524, 525]}
]
Answered By: JonSG

Using pandas you can easily achieve the result.
First install pandas if you don’t have as follow

pip install pandas

import pandas as pd
df = pd.DataFrame(slots_data) #create dataframe
df1 = df.groupby("user_id")['id'].apply(list).reset_index(name="slots_ids") #groupby on user_id and combine elements of id in list and give the column name is slots_ids
final_slots_data = df1.to_dict('records') # convert dataframe into a list of dictionary
final_slots_data

Output:

[{'user_id': 1, 'slots_ids': [551, 552, 553]},
 {'user_id': 2, 'slots_ids': [550]},
 {'user_id': 3, 'slots_ids': [525, 524]}]
Answered By: Vishal Barad