2012-02-20 33 views
2

我有关于一堆不同项目的信息。每个项目都有自己的字典,填充有关于该项目的信息,并且我有一个更大的字典,其中存储每个项目。但是,我没有为每个项目提供所有相同的信息。例如,假设我的物品是水果。然后,结构是这样的:查找所有词典,每个词典都有不确定数量的定义键

fruit = {} 
fruit['apple'] = {'color': 'red', 'origin': 'Washington'} 
fruit['banana'] = {'color': 'yellow'} 
fruit['orange'] = {'color': 'orange', 'origin': 'Florida'} 

如果我想找到它已被定义为每个水果的原产地,我做了以下内容:

fruits, origins = zip(* [(f, fruit[f]['origin']) for f in fruit.keys() if 'origin' in fruit[f]]) 

这工作正常。一旦我想找到每一个同时具有颜色和来源定义的水果,它就开始变得丑陋。

fruits, origins, colors = zip(* [(f, fruit[f]['origin'], fruit[f]['color']) for f in fruit.keys() if 'origin' in fruit[f] and 'color' in fruit[f]]) 

我想要做的是能写,会为任何数量的特定键执行此操作的一般功能。也就是说,我可以调用一个名为“defined”的函数,它将采用字典词典和子字典中的键或键列表,并返回所有包含每个键的定义的子字典,以及每个键的值。

fruits, origins = defined(fruit, ['origin']) 
fruits, origins, colors = defined(fruit, ['origin', 'color']) 

我已经看了各种现有线程与有关获取键/值对的或以以字典的问题,但我还没有发现任何看起来合适的。有没有一种相当直接的方式来推广这一点?或者,如果人们也想告诉我,我应该以完全不同的方式组织我的数据,那么我也会欢迎。由于每个项目可用的信息范围很广,我最初选择了一本词典词典。例如,一些子词典有数十条信息条目,有些条目只有少数条目(即“苹果”字典有很多信息,但我没有太多的储存在'金橘'中)。

回答

4

可以概括通过列表理解的价值提取,and序列由all

def defined(dct, keys): 
    return zip(*[([k] + [v[m] for m in keys]) 
       for k, v in dct.iteritems() 
       if all(m in v for m in keys)]) 
+0

太棒了,这个工作就像我希望的那样。谢谢! – jdmcbr 2012-02-20 23:55:02

2

这是一个以与您的示例调用所建议的方式稍有不同的方式返回数据的函数:它将返回迭代器,该迭代器遍历包含所有必需字段的所有字典条目。

def defined(fruits, attr_names): 
    getter = operator.itemgetter(*attr_names) 
    for f, d in fruit.iteritems(): 
     try: 
      attrs = getter(d) 
     except KeyError: 
      continue 
     else: 
      yield (f,) + attrs 

在执行的唯一的事,可能是值得一提的是operator.itemgetter()。像

operator.itemgetter(['origin', 'color']) 

调用返回的是,适用于一本字典,将返回值的键'origin''color'作为一个元组的函数。如果其中一个密钥不能被唤醒,那么字典将像往常一样抛出KeyError

您可以使用zip()在返回的迭代中你建议的方式来使用此功能:

fruits, origins, colors = zip(*defined(fruit, ['origin', 'color'])) 
+0

谢谢!这对我给的玩具例子有效。出于某种原因,我无法让它为我的真正问题工作,但我将进一步发挥它的作用,并尝试理解这是怎么回事。 – jdmcbr 2012-02-21 00:02:32