我有关于一堆不同物品的信息。每个项目都有自己的字典,其中包含有关该项目的信息,我有一个更大的字典,其中存储了每个项目。但是,我没有为每个项目提供所有相同的信息。例如,假设我的物品是水果。然后结构看起来像:
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'])
我已经查看了各种现有线程,其中包含有关从字典中获取键/值对的问题,但我没有找到任何看起来正确的内容。是否有一种相当直接的方式来概括这一点?
或者,如果人们还想告诉我我应该以完全不同的方式组织我的数据,我也欢迎这样做。我最初选择了字典词典,因为每个项目都有广泛的信息。例如,一些子词典有数十个带有信息的条目,有些项只有几个条目(也就是说,'apple'词典有很多信息,但我没有太多的存储在'金橘'中)。
答案 0 :(得分: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)])
答案 1 :(得分: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']))