我在列表中有一个dict,目前是这样的:
[ {'name': 'Joe',
'score': 98,
'subject': 'Math'},
{'name': 'Bob',
'score': 90,
'subject': 'Math'},
{'name': 'Bill',
'score': 88,
'subject': 'English'},
{'name': 'Jane',
'score': 95,
'subject': 'English'}]
我想按照以下方式重组或重组:
[ {'subject': 'Math',
'Results': [{'name': 'Joe','score':98}, {'name':'Bob', 'score':90}]},
{'subject': 'English',
'Results': [{'name': 'Jane','score':95}, {'name':'Bill', 'score':88}]}
]
我尝试使用itertools.groupby
和dict.setdefault()
作为建议here,但无法完全得到我想要的内容。我怎么能这样做?
答案 0 :(得分:4)
使用小循环和dict.setdefault
,您可以进行如下分组:
grouped = {}
for score in scores:
grouped.setdefault(score['subject'], []).append(
{k: v for k, v in score.items() if k != 'subject'})
要在分组后获得其他输出格式:
grouped = [{'subject': k, 'Results': v} for k, v in grouped.items()]
scores = [
{'name': 'Joe',
'score': 98,
'subject': 'Math'},
{'name': 'Bob',
'score': 90,
'subject': 'Math'},
{'name': 'Bill',
'score': 88,
'subject': 'English'},
{'name': 'Jane',
'score': 95,
'subject': 'English'}]
grouped = {}
for score in scores:
grouped.setdefault(score['subject'], []).append({
k: v for k, v in score.items() if k != 'subject'})
print([{'subject': k, 'Results': v} for k, v in grouped.items()])
[
{'subject': 'Math',
'Results': [{'name': 'Joe', 'score': 98}, {'name': 'Bob', 'score': 90}]},
{'subject': 'English',
'Results': [{'name': 'Bill', 'score': 88}, {'name': 'Jane', 'score': 95}]}
]
答案 1 :(得分:1)
看看itertools.groupby,然后以下代码可能对您有帮助。
[{'subject': k, 'Results': list(g)} for k, g in itertools.groupby(a, key=itemgetter('subject'))]
示例输出:
[{'Results': [{'score': 98, 'name': 'Joe', 'subject': 'Math'}, {'score': 90, 'name': 'Bob', 'subject': 'Math'}], 'subject': 'Math'}, {'Results': [{'score': 88, 'name': 'Bill', 'subject': 'English'}, {'score': 95, 'name': 'Jane', 'subject': 'English'}], 'subject': 'English'}]
答案 2 :(得分:0)
您需要遍历旧列表并将每个元素重新格式化为新元素
#first we need to create the newList in the general format that you want
newList = [{'subject':'math','results':[]},{'subject':'english','results':[]}]
#then we iterate through the elements in the old list and put them into the new list with the new formatting
for i in oldList:
element = 0 if i['subject']=='math' else 'english' #because, in your post, you ordered them this way
#then we need to append the element to the results list
newList[element]['results'].append({'name':i['name'],'score':i['score']})
答案 3 :(得分:0)
在处理从某些字典数据派生的自定义对象时,我喜欢这种语法:
o = [ {'name': 'Joe',
'score': 98,
'subject': 'Math'},
{'name': 'Bob',
'score': 90,
'subject': 'Math'},
{'name': 'Bill',
'score': 88,
'subject': 'English'},
{'name': 'Jane',
'score': 95,
'subject': 'English'}]
r = []
for a in set([b['subject'] for b in o]):
r.append({
'subject': a,
'Results': [{'name':c['name'], 'score':c['score']} for c in o if c['subject']==a ],
})
print(r)
工作代码:repl.it
答案 4 :(得分:0)
如果您想使用collections.defaultdict()
,可以执行以下操作:
from collections import defaultdict
from pprint import pprint
scores = [{'name': 'Joe',
'score': 98,
'subject': 'Math'},
{'name': 'Bob',
'score': 90,
'subject': 'Math'},
{'name': 'Bill',
'score': 88,
'subject': 'English'},
{'name': 'Jane',
'score': 95,
'subject': 'English'}]
result = defaultdict(list)
for score in scores:
temp = {k: _ for k, _ in score.items() if k != 'subject'}
result[score['subject']].append(temp)
pprint([{'subject' : k, 'Results': v} for k, v in result.items()])
给出了:
[{'Results': [{'name': 'Joe', 'score': 98}, {'name': 'Bob', 'score': 90}],
'subject': 'Math'},
{'Results': [{'name': 'Bill', 'score': 88}, {'name': 'Jane', 'score': 95}],
'subject': 'English'}]
答案 5 :(得分:0)
选项1
以下是标准itertools.groupby
方法:
key = "subject"
[{key: k, "Result": {k_: v for d in g for k_, v in d.items() if k_ != key}} for k, g in it.groupby(lst, lambda x: x[key])]
为简单起见,如果给出[k: g for k, g in itertools.groupby(iterable, key)]
形式,则此处g
只会被过滤后的字典理解所取代。 lst
是dicts的输入列表。
选项2
more_itertools.groupby_transform
是第三方配方,其扩展itertools.groupby
以允许更改生成的组:
import copy
import more_itertools as mit
def get_scores(iterable, key):
"""Return resulting ditctionaries grouped by key."""
iterable = copy.deepcopy(iterable) # optional
kfunc = lambda x: x[key]
def vfunc(x):
del x[key]
return x
return [{key: k, "Result": list(g)} for k, g in mit.groupby_transform(iterable, keyfunc=kfunc, valuefunc=vfunc)]
get_scores(lst, "subject")
此处从结果组中删除重复键。删除项目将改变嵌套的词典。为了保留以前嵌套的dicts的某种程度,制作深层照片,即。看到可选行。
答案 6 :(得分:0)
在一行中你可以这样做:
data=[ {'name': 'Joe',
'score': 98,
'subject': 'Math'},
{'name': 'Bob',
'score': 90,
'subject': 'Math'},
{'name': 'Bill',
'score': 88,
'subject': 'English'},
{'name': 'Jane',
'score': 95,
'subject': 'English'}]
import itertools
print({i:list(j) for i,j in itertools.groupby(data,key=lambda x:x['subject'])})
输出:
{'English': [{'subject': 'English', 'score': 88, 'name': 'Bill'}, {'subject': 'English', 'score': 95, 'name': 'Jane'}], 'Math': [{'subject': 'Math', 'score': 98, 'name': 'Joe'}, {'subject': 'Math', 'score': 90, 'name': 'Bob'}]}