1

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).

Joe Ferndz
  • 8,417
  • 2
  • 13
  • 33
Ste
  • 283
  • 1
  • 15
  • do you want to get only SKU's for seperate `shelf`s? is using pandas ok for you? – armamut Jan 17 '21 at 19:24
  • @armamut `pandas` is ok even if I have not considered it. It's a standalone SW. I need to pivot/reorganize everything. I probably need to create a new empty list and in the same def append whatever I need under a key I must create if not exist ... mmm – Ste Jan 17 '21 at 19:26

3 Answers3

2
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.

PieCot
  • 3,564
  • 1
  • 12
  • 20
1
lst = [
  {"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"}
]

lst2 = list()
for dct in lst:
    v = dct.pop("shelf", None) or "default"
    for d in lst2:
        if d.get(v):
            d[v].append(dct)
            break
    else:
        lst2.append({v: [dct]})
print(lst2)

Output:

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

Breaking it down:

  1. Define a list, lst2, to become the output list.

  2. Iterate through the dictionaries of lst, and define a variable, v, to check if the value of the soon-to-be-created-dictionary should be the value of the current dictionary's "shelf" key, or "default".

  3. Iterate through each dictionary of the lst2. If coresponding key are found, append the dictionary to the key of the lst2.

Red
  • 26,798
  • 7
  • 36
  • 58
0

my take on the question, with pandas:

df = pd.DataFrame([
  {"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"}
])
df.shelf = df.shelf.fillna('default')
for shelf, skus in df.groupby('shelf').sku.apply(list).items():
    print(shelf, "=>", skus)
>>>
10.0 => ['ZZZ', 'AAA']
default => ['BBB', 'CCC']

armamut
  • 1,087
  • 6
  • 14