Catalogar uma lista de dicionários
-
22-09-2019 - |
Pergunta
Eu tenho uma lista de dicionários:
people = [{"name": "Roger", "city": "NY", "age": 20, "sex": "M"},
{"name": "Dan", "city": "Boston", "age": 20, "sex": "M"},
{"name": "Roger", "city": "Boston", "age": 21, "sex": "M"},
{"name": "Dana", "city": "Dallas", "age": 30, "sex": "F"}]
Eu quero catalogá -los, por exemplo, escolho estas chaves:
field = ("sex", "age")
Eu preciso de uma função catalogue(field, people)
que me dê:
{ "M":
{ 20: [{"name": "Roger", "city": "NY", "age": 20, "sex": "M"},
{"name": "Dan", "city": "Boston", "age": 20, "sex": "M"}],
21: [{"name": "Roger", "city": "Boston", "age": 21, "sex": "M"}]
},
{ "F":
{ 30: [{"name": "Dana", "city": "Dallas", "age": 30, "sex": "F"}] }
}
quando len(field)==1
é simples. Eu quero fazer algo assim:
c = catalogue(field, people)
for (sex, sex_value) in c.iteritems():
for (age, age_value) in sex_value.iteritems():
print sex, age, age_value["name"]
Solução
recursivamente:
import itertools, operator
def catalog(fields,people):
cur_field = operator.itemgetter(fields[0])
groups = itertools.groupby(sorted(people, key=cur_field),cur_field)
if len(fields)==1:
return dict((k,list(v)) for k,v in groups)
else:
return dict((k,catalog(fields[1:],v)) for k,v in groups)
teste:
import pprint
pprint.pprint(catalog(('sex','age'), people))
{'F': {30: [{'age': 30, 'city': 'Dallas', 'name': 'Dana', 'sex': 'F'}]},
'M': {20: [{'age': 20, 'city': 'NY', 'name': 'Roger', 'sex': 'M'},
{'age': 20, 'city': 'Boston', 'name': 'Dan', 'sex': 'M'}],
21: [{'age': 21, 'city': 'Boston', 'name': 'Roger', 'sex': 'M'}]}}
Outras dicas
import pprint
people = [{"name": "Roger", "city": "NY", "age": 20, "sex": "M"},
{"name": "Dan", "city": "Boston", "age": 20, "sex": "M"},
{"name": "Roger", "city": "Boston", "age": 21, "sex": "M"},
{"name": "Dana", "city": "Dallas", "age": 30, "sex": "F"}]
fields = ("sex", "age")
result = {}
for person in people:
tempdict = result
for field in fields[:-1]:
if person[field] in tempdict:
tempdict = tempdict[person[field]]
else:
t = tempdict
tempdict = {}
t[person[field]] = tempdict
key = person[fields[-1]]
if key in tempdict:
tempdict[key].append(person)
else:
tempdict[key] = [person]
pprint.pprint(result)
parece fazer o trabalho
Não é ideal (poderia ser melhorado usando defaultdict
, por exemplo, mas eu tinha python2.4 instalado na minha máquina), mas faz o trabalho:
def catalogue(dicts, criteria):
if not criteria:
return dicts
criterion, rest = criteria[0], criteria[1:]
cat = {}
for d in dicts:
reducedDict = dict(d)
del reducedDict[criterion]
if d[criterion] in cat:
cat[d[criterion]].append(reducedDict)
else:
cat[d[criterion]] = [reducedDict]
retDict = {}
for key, val in cat.items():
retDict[key] = catalogue(val, rest)
return retDict
print catalogue(people, ("sex", "age"))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow