获取嵌套字典中唯一值的列表(或集合)
Obtaining list (or set) of unique values in nested dictionary
我想知道是否有更多 elegant/pythonic 方法来执行以下操作。假设我有一个嵌套字典:
orders = {'peter': {'food': 'pizza', 'drink': 'soda'}, 'paul': {'food': 'taco', 'drink': 'soda'},'mary': {'food': 'pizza', 'drink': 'water'}}
我想获得一个列表,其中包含每个人的唯一 'food' 项,即['pizza', 'taco']
这是最简单的方法吗?
foodList = []
for i in orders.keys():
foodList.append(orders[i]['food'])
s = set(foodList)
>>> {orders[i]['food'] for i in orders}
{'pizza', 'taco'}
如果 food
的值是列表或元组,您可以在集合理解中使用嵌套循环。
>>> orders = {'peter': {'food': ['pizza','fries'], 'drink': 'soda'}, 'paul': {'food': ['taco'], 'drink': 'soda'}}
>>> {j for i in orders for j in orders[i]['food']}
{'pizza', 'taco', 'fries'}
您甚至可以使用 operator.itemgetter
as mentioned by 。
>>> from operator import itemgetter
>>> set(map(itemgetter("food"), orders.values()))
{'pizza', 'taco'}
同样,如果食物的值是一个列表,您可以使用 chain
。
>>> from itertools import chain
>>> set(chain(*map(itemgetter("food"), orders.values())))
{'pizza', 'taco', 'fries'}
您可以使用 defaultdict- 它寻址列表值。
>>>import collections
>>>from collections import defaultdict
>>>d =defaultdict(list)
>>>orders = {'paul': {'food': ['taco', ['sugar']], 'drink': 'soda'}, 'peter': {'food': 'pizza', 'drink': 'soda'}, 'mary': {'food': 'pizza', 'drink': 'water'}}
>>>for i in orders:
d['food'].append(orders[i]['food'])
>>>def flatten(l):#borrowed
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
for sub in flatten(el):
yield sub
else:
yield el
>>>list(set(flatten(d.values())))
>>>['sugar', 'pizza', 'taco']
如果您得到一份食物清单而不是单一食物:
set(reduce(lambda x,y:x + y, [orders[i]['food'] for i in orders], []))
如果您收集的值是 "immutable",您可以使用集理解来收集不同的值。 @BhargavRao 已经提出了这个建议,但这里有一个更简洁的解决方案:
foods = set( val["food"] for val in orders.values() )
您还询问(在评论中)如果值是列表该怎么做。如果值是 ["pizza", "taco"]
,我假设您希望集合中有 "pizza"
和 "taco"
,而不是 ["pizza", "taco"]
作为元素。如果 some 元素是列表,有些元素是字符串,这有点棘手(设计糟糕;最好到处都有列表,即使它只是一个元素),所以我会逐步进行,像这样:
foods = set()
for val in orders.values():
eat = val["food"]
if isinstance(eat, str):
foods.add(eat) # one item
else:
foods.update(eat) # list or tuple
我想知道是否有更多 elegant/pythonic 方法来执行以下操作。假设我有一个嵌套字典:
orders = {'peter': {'food': 'pizza', 'drink': 'soda'}, 'paul': {'food': 'taco', 'drink': 'soda'},'mary': {'food': 'pizza', 'drink': 'water'}}
我想获得一个列表,其中包含每个人的唯一 'food' 项,即['pizza', 'taco']
这是最简单的方法吗?
foodList = []
for i in orders.keys():
foodList.append(orders[i]['food'])
s = set(foodList)
>>> {orders[i]['food'] for i in orders}
{'pizza', 'taco'}
如果 food
的值是列表或元组,您可以在集合理解中使用嵌套循环。
>>> orders = {'peter': {'food': ['pizza','fries'], 'drink': 'soda'}, 'paul': {'food': ['taco'], 'drink': 'soda'}}
>>> {j for i in orders for j in orders[i]['food']}
{'pizza', 'taco', 'fries'}
您甚至可以使用 operator.itemgetter
as mentioned by
>>> from operator import itemgetter
>>> set(map(itemgetter("food"), orders.values()))
{'pizza', 'taco'}
同样,如果食物的值是一个列表,您可以使用 chain
。
>>> from itertools import chain
>>> set(chain(*map(itemgetter("food"), orders.values())))
{'pizza', 'taco', 'fries'}
您可以使用 defaultdict- 它寻址列表值。
>>>import collections
>>>from collections import defaultdict
>>>d =defaultdict(list)
>>>orders = {'paul': {'food': ['taco', ['sugar']], 'drink': 'soda'}, 'peter': {'food': 'pizza', 'drink': 'soda'}, 'mary': {'food': 'pizza', 'drink': 'water'}}
>>>for i in orders:
d['food'].append(orders[i]['food'])
>>>def flatten(l):#borrowed
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
for sub in flatten(el):
yield sub
else:
yield el
>>>list(set(flatten(d.values())))
>>>['sugar', 'pizza', 'taco']
如果您得到一份食物清单而不是单一食物:
set(reduce(lambda x,y:x + y, [orders[i]['food'] for i in orders], []))
如果您收集的值是 "immutable",您可以使用集理解来收集不同的值。 @BhargavRao 已经提出了这个建议,但这里有一个更简洁的解决方案:
foods = set( val["food"] for val in orders.values() )
您还询问(在评论中)如果值是列表该怎么做。如果值是 ["pizza", "taco"]
,我假设您希望集合中有 "pizza"
和 "taco"
,而不是 ["pizza", "taco"]
作为元素。如果 some 元素是列表,有些元素是字符串,这有点棘手(设计糟糕;最好到处都有列表,即使它只是一个元素),所以我会逐步进行,像这样:
foods = set()
for val in orders.values():
eat = val["food"]
if isinstance(eat, str):
foods.add(eat) # one item
else:
foods.update(eat) # list or tuple