2010-03-24 79 views
2

我的词典列表:目录词典列表

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

我想目录它们,例如我选择这些键:

field = ("sex", "age") 

我需要一个函数catalogue(field, people),让我:

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

len(field)==1这很简单。我想要做这样的事情:

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"] 
+0

另一个简单的问题:这个函数的名字是什么?我用'catalog',可以吗? – 2010-03-25 10:53:14

+0

目录似乎没问题 – 2010-03-25 12:27:05

回答

8

递归:

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) 

测试:

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'}]}} 
+2

永远不会使用'import *'。 – 2010-03-24 16:37:01

+2

:)好的,修正 – Jimmy 2010-03-24 16:45:30

+1

一个有用的注意事项是,您可以使用operator.itemgetter工厂函数创建查找函数。即用'cur_field = operator.itemgetter(fields [0])替换第一行''这看起来好一点,而且稍微快一点。 – Brian 2010-03-24 17:10:33

0
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) 

似乎做的工作

0

不是最佳的(可以改善使用defaultdict,fo r实例,但我在我的机器上安装了Python2.4),但是完成这项工作:

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"))