Реорганизовать список словарей

Предполагая, что у меня есть следующее:

      [
  {"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"}
]

Я пытаюсь найти лучший (возможно, самый элегантный) способ:

  1. Добавить «полку»: «По умолчанию», если отсутствует или установлено значение None
  2. Разделите список на полку, чтобы приведенный выше список выдавал два именованных списка: один для «По умолчанию» и один для «10». Это желаемый результат:
      [
  {"10":[
    {"sku": "ZZZ", "name":"None name"},
    {"sku": "AAA", "name":"One name"}]
  },
  {"default":[
    {"sku": "CCC", "name":"A name"},
    {"sku": "BBB", "name":"The name"]
  }
]

С использованием pydash.collections.for_each(initial_list,reorganize)Я могу решить первую проблему, но я не уверен, как справиться со второй.

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

Я также не думаю, что это лучший способ решить проблему. Причина для поворота списка заключается в том, что мне нужно вызвать API, которому требуется полка в качестве параметра, и который не может одновременно принимать несколько полок (но принимает несколько SKU).

3 ответа

      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является:

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

Поясним код:

  • возвращает запись и удаляет ее из словаря; если нет, возвращает значение по умолчанию, т.е. его второй (необязательный) аргумент ( 'default'в таком случае). orиспользуется для обработки случаев, когда присутствует, но с Noneили '' значение: в этом случае, defaultиспользуется.

  • setdefaultвозвращает значение словаря с ключом, равным
    первому аргументу, или возвращает второй аргумент, если ключ отсутствует
    .

  • appendдобавляет текущий словарь (с записью, удаленной pop) в список, соответствующий его shelfценность.

      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)

Выход:

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

Разбивая это:

  1. Определите список, который станет выходным списком.

  2. Итерация по словарям lst, и определить переменную, v, чтобы проверить, должно ли значение словаря, который скоро будет создан, быть значением текущего словаря. "shelf"ключ или "default".

  3. Перебрать каждый словарь файла . Если соответствующий ключ найден, добавьте словарь к ключу lst2.

мой взгляд на вопрос с пандами:

      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']

Другие вопросы по тегам