获取嵌套字典中唯一值的列表(或集)

时间:2015-12-05 20:34:25

标签: python list dictionary set

我想知道是否有更优雅/ pythonic的方式来执行以下操作。假设我有一个嵌套字典:

orders = {'peter': {'food': 'pizza', 'drink': 'soda'}, 'paul': {'food': 'taco', 'drink': 'soda'},'mary': {'food': 'pizza', 'drink': 'water'}}

我希望获得一份包含独特食物的清单。每个人的物品,即每个人。 ['pizza', 'taco']

这是最简单的方法吗?

foodList = []
for i in orders.keys():
    foodList.append(orders[i]['food'])
s = set(foodList)

4 个答案:

答案 0 :(得分:8)

使用set comprehension

>>> {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所述的Padraic

>>> 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'}

答案 1 :(得分:0)

您可以使用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']

答案 2 :(得分:0)

如果你得到食物清单而不是单一食物:

set(reduce(lambda x,y:x + y, [orders[i]['food'] for i in orders], []))

答案 3 :(得分:0)

如果您收集的值是" immutable",您可以使用集合理解来收集不同的值。 @BhargavRao已经提出了这个建议,但这是一个更清洁的解决方案:

foods = set( val["food"] for val in orders.values() )

如果值是列表,您还会(在评论中)询问该怎么做。如果值为["pizza", "taco"],我假设您希望集合中包含"pizza""taco",而不是["pizza", "taco"]作为元素。如果某些元素是列表而某些是字符串(设计不佳;在任何地方都有列表,即使它只是一个元素),这有点棘手,所以我会逐步地这样做:

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