Search code examples
pythonpython-3.xpydash

Reorganize a list of dictionaries


Assuming I have the following:

[
  {"sku": "ZZZ", "name":"None name","shelf": 10},
  {"sku": "AAA", "name":"One name","shelf": 10},
  {"sku": "BBB", "name":"The name", "shelf": None},
  {"sku": "CCC", "name":"A name"}
]

I am trying to find the best (most elegant maybe) way to:

  1. Add "shelf": 'Default' when missing or set to None
  2. Split the list per shelf, so the one above should give out two named lists: one for Default and one for '10' This is the desired output:
[
  {"10":[
    {"sku": "ZZZ", "name":"None name"},
    {"sku": "AAA", "name":"One name"}]
  },
  {"default":[
    {"sku": "CCC", "name":"A name"},
    {"sku": "BBB", "name":"The name"]
  }
]

Using pydash.collections.for_each(initial_list,reorganize) I can sort the first problem, but I am not sure how to deal with the second.

def reorganize(x):
    if 'shelf' not in x: x['shelf'] = 'default'
    if x['shelf'] is None: x['shelf'] = 'default'

I also do not thing this is the best way to solve the problem. Reason for pivoting the list is because I need to call an API which needs the shelf as parameter and cannot accept multiple shelf at the same time (but accepts multiple SKUs).


Solution

  • input_list = [
      {"sku": "ZZZ", "name":"None name","shelf": 10},
      {"sku": "AAA", "name":"One name","shelf": 10},
      {"sku": "BBB", "name":"The name", "shelf": None},
      {"sku": "CCC", "name":"A name"}
    ]
    
    output_dict = {}
    for d in input_list:
        output_dict.setdefault(d.pop('shelf', 'default') or 'default', []).append(d)
    

    output_dict is:

    {10: [{'sku': 'ZZZ', 'name': 'None name'}, {'sku': 'AAA', 'name': 'One name'}], 'default': [{'sku': 'BBB', 'name': 'The name'}, {'sku': 'CCC', 'name': 'A name'}]}
    

    Let's explain the code:

    • pop returns the shelf entry and removes it from the dictionary; if shelf is not present, pop returns the default value, i.e. its second (optional) argument ('default' in this case). The or is used to handle the cases when shelf is present, but with a None or '' value: in this case, default is used.

    • setdefault returns the value of the dictionary with key equal to
      the first argument, or it returns the second argument if the key is
      not present.

    • append adds the current dictionary (with shelf entry removed by pop) to the list corresponding to its shelf value.