Kirill
Kirill

Reputation: 3

Merge two arrays by keys in Python

I have two arrays. "Categories" and "Products". I need to get a third array where in each category there will be a list of products to which it belongs.

categories = [
    {
        'id': 1,
        'name': 'first category'
    },
    {
        'id': 2,
        'name': 'second category'
    },
    {
        'id': 3,
        'name': 'third category'
    },
]

products = [
    {
        'id': 1,
        'id_category': 1,
        'name': 'first product'
    },
    {
        'id': 2,
        'id_category': 2,
        'name': 'second product'
    },
    {
        'id': 3,
        'id_category': 2,
        'name': 'third product'
    },
]

I need to combine these two arrays into one, by "id_category", to get the following:

the conditions must be met:

if there are no products in the category, then remove category from the list;

products_by_category = [
   {
      "id":1,
      "name":"first category",
      "products":[
         {
            "id":1,
            "name":"first product"
         }
      ]
   },
   {
      "id":2,
      "name":"second category",
      "products":[
         {
            "id":2,
            "name":"second product"
         },
         {
            "id":3,
            "name":"third product"
         }
      ]
   }
]

i tried the following code:

for category in list(categories):
    category['products'] = []
    for product in products:
        if category['id'] == product['id_category']:
            category['products'].append(product)
    
    if not category['products']:
        categories.remove(category)

print(categories)

Upvotes: 0

Views: 1333

Answers (2)

sushanth
sushanth

Reputation: 8302

Here is another approach using defaultdict, create a lookup between id_category along with there details. Followed by list comprehension to update back to categories.

from collections import defaultdict

# create a mapping for each product
prod_lookup = defaultdict(list)

for prod in products:
    prod_lookup[prod['id_category']].append(
        {"id": prod['id'], "name": prod['name']}
    )

# update back to categories, based on "id"
(
    [{**cat, **{"products": prod_lookup.get(cat['id'], [])}}
     for cat in categories if prod_lookup.get(cat['id'])]
)

Upvotes: 0

Sandeep Datta
Sandeep Datta

Reputation: 29345

Here is something which does what you want. Note it does not create a new data structure just updates the categories in place.

catdict = {cat['id']:cat for cat in categories}

for product in products:
    pcat = product['id_category']
    del product['id_category']
    cat = catdict[pcat]
    if not "products" in cat:
        cat["products"] = []
        
    cat["products"].append(product)
    
print(categories)

Upvotes: 1

Related Questions