Реорганизовать список словарей
Предполагая, что у меня есть следующее:
[
{"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"}
]
Я пытаюсь найти лучший (возможно, самый элегантный) способ:
- Добавить «полку»: «По умолчанию», если отсутствует или установлено значение
None
- Разделите список на полку, чтобы приведенный выше список выдавал два именованных списка: один для «По умолчанию» и один для «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'}]}]
Разбивая это:
Определите список, который станет выходным списком.
Итерация по словарям
lst
, и определить переменную,v
, чтобы проверить, должно ли значение словаря, который скоро будет создан, быть значением текущего словаря."shelf"
ключ или"default"
.Перебрать каждый словарь файла . Если соответствующий ключ найден, добавьте словарь к ключу
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']