How to fetch data from tuple into dictionary?

Question:

I have a tuple:

items = (
    (1, {"name": "computer", "price": 20000, "quantity": 5, "ed": "pcs."}),
    (2, {"name": "printer", "price": 6000, "quantity": 2, "ed": "pcs."}), 
    (3, {"name": "scanner", "price": 2000, "quantity": 7, "ed": "pcs."})
)

My task is to create a dict like this:

basket = {
    "Name": ["computer", "printer", "scanner"],
    "Price": [20000, 6000, 2000],
    "Amount": [5, 2, 7],
    "Unit": ["piece"]
}

What I did:

I was able to print out data that I need using this code:

converted_items = dict(items)
for items in converted_items:
    print(list(converted_items[items].keys())[0])
    for i in converted_items[items].values():
        print(i)

Resulting in each word in a new line:

name
computer
20000
5
pcs
name
printer
6000
2
pcs and so on...
Asked By: Konstantin F

||

Answers:

Simply convert the tuple to a DataFrame and then to a dictionary
To convert to a dataFrame, convert tuple into a list of dictionaries using list comprehension

items = ((1, {"name": "computer", "price": 20000, "quantity": 5, "ed": "pcs."}),
        (2, {"name": "printer", "price": 6000, "quantity": 2, "ed": "pcs."}),
        (3, {"name": "scanner", "price": 2000, "quantity": 7, "ed": "pcs."}))
df = pd.DataFrame([item[1] for item in items])
df.to_dict(orient='list')

Output

{'name': ['computer', 'printer', 'scanner'],
 'price': [20000, 6000, 2000],
 'quantity': [5, 2, 7],
 'ed': ['pcs.', 'pcs.', 'pcs.']}
Answered By: Shubham Periwal

IMO pandas would be complete overkill for something relatively straight-forward like this — the proof is below:

tems = (
    (1, {"name": "computer", "price": 20000, "quantity": 5, "ed": "pcs."}),
    (2, {"name": "printer", "price": 6000, "quantity": 2, "ed": "pcs."}),
    (3, {"name": "scanner", "price": 2000, "quantity": 7, "ed": "pcs."})
)
source_keys = 'name', 'price', 'quantity', 'ed'
target_keys = 'Name', 'Price', 'Amount', 'Unit'

basket = {key: [] for key in target_keys}  # Initialize to empty lists.
for _, item in items:
    for source_key, target_key in zip(source_keys, target_keys):
        basket[target_key].append(item[source_key])

from pprint import pprint
pprint(basket)

Output:

{'Amount': [5, 2, 7],
 'Name': ['computer', 'printer', 'scanner'],
 'Price': [20000, 6000, 2000],
 'Unit': ['pcs.', 'pcs.', 'pcs.']}
Answered By: martineau

Shortest, but least robust solution for this specific case

items = (
            (1, {"name": "computer", "price": 20000, "quantity": 5, "ed": "pcs."}),
            (2, {"name": "printer", "price": 6000, "quantity": 2, "ed": "pcs."}),
            (3, {"name": "scanner", "price": 2000, "quantity": 7, "ed": "pcs."})
        )
basket = {k: [v[1][k] for v in items] for k in items[0][1].keys()}

# now print basket
for k, v in basket.items():
    print(f"{k} = {v}")

<script src="https://modularizer.github.io/pyprez/pyprez.min.js"></script>

Personally suggested, more robust solution

# py
def list_of_dicts_to_dict_of_list(list_of_dicts, shared_keys_only=False, default_value=None):
    """
    convert a list of dictionaries into a dictionary of lists

    :param list_of_dicts: list of dictionaries
    :type list_of_dicts: list
    :param shared_keys_only: whether to include keys which are only in some of the dictionaries
    :type shared_keys_only: bool
    :param default_value: value to insert if shared_keys_only is True and a list does not contain one of the keys
    :type object: any type
    :return: dictionary of lists
    :type: dict
    """
    item_dict_keys = [list(d.keys()) for d in list_of_dicts]
    keys_in_any = [k for inner_list in item_dict_keys for k in inner_list]
    keys_in_all = [k for k in keys_in_any if all([k in d for d in list_of_dicts])]
    if shared_keys_only:
        keys = keys_in_all
    else:
        keys = keys_in_any
    unique_keys = list(set(keys))
    dict_of_lists = {k: [d[k] if k in d else default_value for d in list_of_dicts] for k in unique_keys}
    return dict_of_lists
    
items = (
            (1, {"name": "computer", "price": 20000, "quantity": 5, "ed": "pcs."}),
            (2, {"name": "printer", "price": 6000, "quantity": 2, "ed": "pcs."}),
            (3, {"name": "scanner", "price": 2000, "quantity": 7, "ed": "pcs."})
        )
item_dicts = [v[1] for v in items]
basket = list_of_dicts_to_dict_of_list(item_dicts)

# now print basket
for k, v in basket.items():
        print(f"{k} = {v}")

<script src="https://modularizer.github.io/pyprez/pyprez.min.js"></script>

In-depth explanation

items = (
    (1, {"name": "computer", "price": 20000, "quantity": 5, "ed": "pcs."}),
    (2, {"name": "printer", "price": 6000, "quantity": 2, "ed": "pcs."}),
    (3, {"name": "scanner", "price": 2000, "quantity": 7, "ed": "pcs."})
)
# remove unnecessary data
# using a list comprehension, we can do the following
item_dicts = [t[1] for t in items]
# ^ this is the same as:
item_dicts = []
for t in items:
    item_dicts.append(t[1])

# now find the keys we want in the dictionary
# first get a list of a list of keys from each dictionary
item_dict_keys = [list(d.keys()) for d in item_dicts]

# now flatten the 2d list into a 1d list
flat_dict_keys = [k for inner_list in item_dict_keys for k in inner_list]
# ^ this is equivalent to:
flat_dict_keys = []
for inner_list in item_dict_keys:
    for k in inner_list:
        flat_dict_keys.append(k)

# now get the unique values in flat_dict_keys
unique_dict_keys = list(set(flat_dict_keys))

# if not all of the dictionaries have the same keys, we will need a default value.
default_value = None

# use a dict comprehension with a list comprehension inside of it
basket = {k: [d[k] if k in d else default_value for d in item_dicts] for k in unique_dict_keys}
# ^ this is the same as:
basket = {}
for k in unique_dict_keys:
    val = []
    for d in item_dicts:
        if k in d:
            val.append(k)
        else:
            val.append(default_value)
Answered By: Modularizer
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.