我需要有关在Python中按键对字典列表进行分组的帮助。我有字典列表:
raw_values = [
{'qty': 1, 'price': 11.0, 'name': 'Name 1', 'id': '111'},
{'qty': 2, 'price': 22.0, 'name': 'Name 2', 'id': '111'},
{'qty': 3, 'price': 33.0, 'name': 'Name 3', 'id': '111'},
{'qty': 0, 'price': 12.0, 'name': 'Name 1', 'id': '222'},
{'qty': 3, 'price': 13.0, 'name': 'Name 2', 'id': '222'},
{'qty': 7, 'price': 14.0, 'name': 'Name 2', 'id': '333'},
{'qty': 10, 'price': 15.0, 'name': 'Name 3', 'id': '333'}]
基于该列表,我需要创建一个新的词典列表,在该列表中,我可以按“ id”键对记录进行分组,还可以正确重命名并填充其他列-name和qty(如果某些“ id”不是任何记录)我需要将它们留空)。所需的输出:
sorted_values = [
{"id": "111",
"name_1_price": 11.0, "name_1_qty": 1,
"name_2_price": 22.0, "name_2_qty": 2,
"name_3_price": 33.0, "name_3_qty": 3},
{"id": "222",
"name_1_price": 12.0, "name_1_qty": 0,
"name_2_price": 13.0, "name_2_qty": 3,
"name_3_price": None, "name_3_qty": None
},
{"id": "333",
"name_1_price": None, "name_1_qty": None,
"name_2_price": 14, "name_2_qty": 7,
"name_3_price": 15.0, "name_3_qty": 10
}
]
我试图搜索解决方案,我认为我需要使用itertools.groupby
函数来按'id'键进行分组。
但是我不知道-如何根据'id'分组并根据'name'中的值重命名和填充字典?
答案 0 :(得分:0)
Pandas解决方案:
import pandas as pd
raw_values = [
{'qty': 1, 'price': 11.0, 'name': 'Name 1', 'id': '111'},
{'qty': 2, 'price': 22.0, 'name': 'Name 2', 'id': '111'},
{'qty': 3, 'price': 33.0, 'name': 'Name 3', 'id': '111'},
{'qty': 0, 'price': 12.0, 'name': 'Name 1', 'id': '222'},
{'qty': 3, 'price': 13.0, 'name': 'Name 2', 'id': '222'},
{'qty': 7, 'price': 14.0, 'name': 'Name 2', 'id': '333'},
{'qty': 10, 'price': 15.0, 'name': 'Name 3', 'id': '333'}]
#create DataFrame from dictionary
df = pd.DataFrame(raw_values)
print (df)
id name price qty
0 111 Name 1 11.0 1
1 111 Name 2 22.0 2
2 111 Name 3 33.0 3
3 222 Name 1 12.0 0
4 222 Name 2 13.0 3
5 333 Name 2 14.0 7
6 333 Name 3 15.0 10
#change value to lower and replace empty spaces
df['name'] = df['name'].str.lower().str.replace('\s+','_')
#reshape by unstack, sorting
df = df.set_index(['id','name']).unstack().sort_index(level=1, axis=1).swaplevel(1,0,axis=1)
#flatten MultiIndex
df.columns = df.columns.map('_'.join)
df = df.reset_index()
#convert NaN to None
df = df.mask(df.isnull(), None)
#convert to list of dicts
L = df.to_dict(orient='records')
print (L)
[{'id': '111',
'name_1_price': 11.0, 'name_1_qty': 1.0,
'name_2_price': 22.0, 'name_2_qty': 2.0,
'name_3_price': 33.0, 'name_3_qty': 3.0},
{'id': '222',
'name_1_price': 12.0, 'name_1_qty': 0.0,
'name_2_price': 13.0, 'name_2_qty': 3.0,
'name_3_price': None, 'name_3_qty': None},
{'id': '333',
'name_1_price': None, 'name_1_qty': None,
'name_2_price': 14.0, 'name_2_qty': 7.0,
'name_3_price': 15.0, 'name_3_qty': 10.0}]
答案 1 :(得分:0)
您可以执行以下操作(在纯python中):
grouped = {}
for row in raw_values:
if row['id'] not in grouped:
grouped[row['id']] = []
grouped[row['id']].append((row['qty'], row['price'], row['name']))
output = []
for ID in grouped:
item = {'id': ID}
for (q, p, n) in grouped[ID]:
item[n + '_qty'] = q
item[n + '_price'] = p
output.append(item)
print(output)
输出将是:
[{'Name 1_qty': 0, 'id': '222', 'Name 2_qty': 3, 'Name 2_price': 13.0, 'Name 1_price': 12.0}, {'Name 1_qty': 1, 'id': '111', 'Name 2_
qty': 2, 'Name 3_price': 33.0, 'Name 3_qty': 3, 'Name 1_price': 11.0, 'Name 2_price': 22.0}, {'Name 3_price': 15.0, 'id': '333', 'Nam
e 2_qty': 7, 'Name 3_qty': 10, 'Name 2_price': 14.0}]
答案 2 :(得分:0)
很简单,但这是我的解决方案。您可以自定义数量名称的数量:
def byId(el):
return el['id']
raw_values = [
{'qty': 1, 'price': 11.0, 'name': 'Name 1', 'id': '111'},
{'qty': 2, 'price': 22.0, 'name': 'Name 2', 'id': '111'},
{'qty': 3, 'price': 33.0, 'name': 'Name 3', 'id': '111'},
{'qty': 0, 'price': 12.0, 'name': 'Name 1', 'id': '222'},
{'qty': 3, 'price': 13.0, 'name': 'Name 2', 'id': '222'},
{'qty': 7, 'price': 14.0, 'name': 'Name 2', 'id': '333'},
{'qty': 10, 'price': 15.0, 'name': 'Name 3', 'id': '333'}]
names = 3
vals = {el['id']:[] for el in raw_values}
for key in vals.keys():
vals[key] = [{f'name_{i+1}_price':None,f'name_{i+1}_qty':None} for i in range(names)]
for el in raw_values:
i = el['name'][-1]
vals[el['id']][int(i)-1][f'name_{i}_price'] = el['price']
vals[el['id']][int(i)-1][f'name_{i}_qty'] = el['qty']
sorted_vals = []
for i,lsts in vals.items():
element = {"id":i}
for el in lsts:
element = {**element, **el}
sorted_vals.append(element)
sorted_vals = sorted(sorted_vals,key = byId)
print(sorted_vals)