0

i have some problem so i have to merge a separated dicts inside list, and display it like what expected code below

so i have this data :

product_data = [
        {
            'productId': 1000,
            'productName': 'Product 1000'
        },
        {
            'productId': 1001,
            'productName': 'Product 1001'
        }
    ]

stock_data = [
        {
            'productId': 1000,
            'locationId': 1,
            'stock': 21
        },
        {
            'productId': 1000,
            'locationId': 2,
            'stock': 8
        },
        {
            'productId': 1001,
            'locationId': 1,
            'stock': 4
        },
        {
            'productId': 1001,
            'locationId': 2,
            'stock': 10
        }
    ]

location_data = [
        {
            'locationId': 1,
            'locationName': 'Location 1'
        },
        {
            'locationId': 2,
            'locationName': 'Location 2'
        }
    ]

i have build some method to process it's relation. like this :

def location_detail(self, location_id):
    location_detail = dict()
    for data in self.location_data:
        if data.get('locationId') == location_id:
            location_detail = {
                'locationName': data.get('locationName')
            }
    return location_detail

def total_stock(self, product_id):
    total = 0
    for data in self.stock_data:
        if data.get('productId') == product_id:
            total += data.get('stock')
    return total

def stock_detail(self, product_id):
    stock_detail = []
    for data in self.stock_data:
        if data.get('productId') == product_id:
            stock_detail.append(
                {
                    'stock': data.get('stock'),
                    'location': 
self.location_detail(data.get('locationId')).get('locationName')
                }
            )
    return stock_detail

def get(self):
    result = []
    for data in self.product_data:
        product_id = data.get('productId')
        product_data = {
            'productName': data.get('productName'),
            'stock': {
                'total': self.total_stock(product_id),
                'detail': self.stock_detail(product_id)
            }
        }
        result.append(product_data)
    return result

the expected result is:

const result = [
{
  productName: 'Product 1000',
  stock: {
  total: 29,
  detail: [
    {
      locationName: 'Location 1',
      stock: 21
    },
    {
      locationName: 'Location 2',
      stock: 8
    }
  ]
 }
},
{
productName: 'Product 1001',
stock: {
  total: 14,
  detail: [
    {
      locationName: 'Location 1',
      stock: 4
    },
    {
      locationName: 'Location 2',
      stock: 10
       }
      ]
   }
 }
  ];

but it takes too many for loops, it didn't meet the requirements. what i want is, get all data with it's relation without having so many for loops.

1
  • Preprocess your lists to be dicts with a lookup key that matches what you're looking for instead; that way you iterate over each list once, and then use a key lookup in your main loop. Commented Aug 21, 2021 at 10:52

2 Answers 2

0

The only thing I can think of, what they've meant is to use list-comprehension instead of for loops.

Some links which you may find useful on the topic:

def aggregate_stock_data(prod_inf, stock_inf, loc_inf):
    loc_inf = {loc['locationId']: loc['locationName'] for loc in loc_inf}
    stock_inf = {
        prod['productId']: list(filter(
            lambda x: x['productId'] == prod['productId'],
            stock_inf
        )) for prod in prod_inf
    }
    aggregated = [
        {
            'productName': prod['productName'],
            'stock': {
                'total': sum(
                    item['stock']
                    for item in stock_inf[prod['productId']]
                ),
                'detail': [
                    {
                        'stock': item['stock'],
                        'locationName': loc_inf[item['locationId']]
                    } for item in stock_inf[prod['productId']]
                ]
            }
        } for prod in prod_inf
    ]
    return aggregated

If for some reason this is not the case, you can always use the map function. But I think that it usually makes the code more unreadable than it already is.

def aggregate_stock_data(prod_inf, stock_inf, loc_inf):
    loc_inf = {loc['locationId']: loc['locationName'] for loc in loc_inf}
    stock_inf = {
        prod['productId']: list(filter(
            lambda x: x['productId'] == prod['productId'],
            stock_inf
        )) for prod in prod_inf
    }
    aggregated = list(map(
        lambda prod: {
            'productName': prod['productName'],
            'stock': {
                'total': sum(map(
                    lambda x: x['stock'],
                    stock_inf[prod['productId']])
                ),
                'detail': list(map(
                    lambda x: {
                        'stock': x['stock'],
                        'locationName': loc_inf[x['locationId']]
                    }, stock_inf[prod['productId']]
                ))
            }
        }, prod_inf
    ))
    return aggregated
Sign up to request clarification or add additional context in comments.

Comments

0

This iterates through the lists once, with the exception of the stock_data.

# convert the location_data into a dict for easy lookup
locations = dict()
for location in location_data:
    locations[location["locationId"]] = location["locationName"]

# convert the stock_data into a dict for easy lookup
stocks = dict()
for stock in stock_data:
    if stock["productId"] in stocks:
        stocks[stock["productId"]]["stockamounts"][stock["locationId"]] = stock["stock"]
        stocks[stock["productId"]]["total"] += stock["stock"]
    else:
        stocks[stock["productId"]] = {
            "total": stock["stock"],
            "stockamounts": {stock["locationId"]: stock["stock"]},
        }

# iterate through the products
result = list()
for product in product_data:
    # set the simple variables
    item = {
        "productName": product["productName"],
        "stock": {
            "total": stocks[product["productId"]]["total"],
            "detail": []}
    }
    # populate the detail list
    for key, value in stocks[product["productId"]]["stockamounts"].items():
        item["stock"]["detail"].append({
            "locationName": locations[key],
            "stock": value
            })
    result.append(item)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.