Python 迭代字典以创建列表

Python 迭代字典以创建列表,python,mongodb,dictionary,pymongo,aggregation-framework,Python,Mongodb,Dictionary,Pymongo,Aggregation Framework,在名为favoriteColors的MongoDB集合中,我有以下4个字典: { "name" : "Johnny", "color" : "green" } { "name" : "Steve", "color" : "blue" }, { "name" : "Ben", "color" : "red" }, { "name" : "Timmy", "color" : "cyan" } 我正在尝试创建一个颜色值的有序列表,与不同的有序列表相匹配 例如,如果我有列表[“Johnny”、“Ste

在名为
favoriteColors
的MongoDB集合中,我有以下4个字典:

{ "name" : "Johnny", "color" : "green" }
{ "name" : "Steve", "color" : "blue" },
{ "name" : "Ben", "color" : "red" },
{ "name" : "Timmy", "color" : "cyan" }
我正在尝试创建一个颜色值的有序列表,与不同的有序列表相匹配

例如,如果我有列表
[“Johnny”、“Steve”、“Ben”、“Johnny”]
,新列表将
[“绿色”、“蓝色”、“红色”、“绿色”]

如果我有这个列表,新的列表将是蓝色、蓝色、红色、红色、绿色

使用Python和/或PyMongo做这件事的好方法是什么。这是我到目前为止所拥有的,但它无法识别重复项

name_list = ["Steve", "Steve", "Ben", "Ben", "Johnny"]

color_list = []
for document in db.favoriteColors.aggregate([
    {"$match": {"name": {"$in": name_list }}},
    {"$project": {"color": 1}}
]):
    for k, v in document.iteritems():
        color_list.append(v)

print color_list
# ["blue", "red", "green"]

如果数据集很小,可以将dict合并成一个新dict

在python3中,您可以执行以下操作:

names = ["Steve", "Steve", "Ben", "Ben", "Johnny"]
favorites = {d["name"]: d["color"] for d in db.favoriteColors.find()}
colors = [favorites[name] for name in names]
print(colors)
更新
正如styvane提到的,我忘记调用
集合上的
find
方法。答案相应更新。

您还可以从当前的dict创建一个新的
dict
,其中
dict[“名称”]
的每个值都将与
dict[“颜色”]
值相关联

例如:新的dict将类似于:

{"Jhonny": "green", "Steve": "blue"}
您可以使用如下示例中的函数,该函数接受多个参数并返回所需的列表(如果输入列表中有任何名称在默认DICS中不存在,它还会附加
None
):

以下是我的例子:

a = { "name" : "Johnny", "color" : "green" }
b = { "name" : "Steve", "color" : "blue" }
c = { "name" : "Ben", "color" : "red" }
d = { "name" : "Timmy", "color" : "cyan" }

my_list = ["Steve", "Steve", "Ben", "Ben", "Johnny"]

def iter_func(my_list = list, *args):
    ne = {k["name"]:k["color"] for k in args}
    return [ne[k] if k in ne.keys() else None for k in my_list]
输出:

print(iter_func(my_list, a,b,c,d))
>>> ['blue', 'blue', 'red', 'red', 'green']
print(iter_func(my_list, a,b,c,d))
>>> ['blue', 'blue', None, 'red', 'red', 'green', None]
具有
None
值的示例:

a = { "name" : "Johnny", "color" : "green" }
b = { "name" : "Steve", "color" : "blue" }
c = { "name" : "Ben", "color" : "red" }
d = { "name" : "Timmy", "color" : "cyan" }

my_list = ["Steve", "Steve", "Alex", "Ben", "Ben", "Johnny", "Mark"]

def iter_func(my_list = list, *args):
    ne = {k["name"]:k["color"] for k in args}
    return [ne[k] if k in ne.keys() else None for k in my_list]
输出:

print(iter_func(my_list, a,b,c,d))
>>> ['blue', 'blue', 'red', 'red', 'green']
print(iter_func(my_list, a,b,c,d))
>>> ['blue', 'blue', None, 'red', 'red', 'green', None]

实际上,我们可以使用聚合框架和客户端处理来高效地完成这项工作

import pymongo


client = pymongo.MongoClient()
db = client.test # Or whatever is your database
favoriteColors = db.favoriteColors
first_list = ['Johnny', 'Steve', 'Ben', 'Johnny']

cursor = favoriteColors.aggregate([
    {'$match': {'name': {'$in': first_list}}}, 
    {'$project': {'part': {'$map': {
        'input': first_list, 
        'as': 'inp', 
        'in': {
            '$cond': [
                {'$eq': [ '$$inp', '$name']}, 
                '$color', 
                None
            ]
        }
    }}}},
    {'$group': {'_id': None, 'data': {'$push': '$part'}}}
])
因为我们不需要,所以光标包含一个文档,我们可以使用
next
检索该文档。事实上,我们可以通过
print(list(cursor))

从这里开始,我们需要使用解压文档中的“数据”字段,使用链接输入,并过滤掉
None
的元素

from itertools import chain

result = [item 
          for item in chain.from_iterable(zip(*next(cursor)['data']))
          if item is not None]
返回:

>>> result
['green', 'blue', 'red', 'green']

您能否创建
'name'
->
'color'
的映射,然后将该映射与
name\u list
一起使用以构建颜色列表?我对mongodb的了解还不够,不知道这是否可以有效地实现,但似乎它可能……不是实现这一点的方法。如果你有一百万个文档与你的查询相匹配呢?OP没有说他的查询像你说的那么大。但是谢谢你的评论。我将尝试改进我的答案。集合对象不可编辑。如果字典是python的,并且几乎没有数据可供迭代,那么这是一种干净的方法。@jcmetz21我看不出这是一种干净的方法
db.favoriteColors
是一个
集合
对象,未实现迭代器协议,因此此查询将返回我提到的TypeError。如果我将字典放入列表中并在列表中进行迭代,则此查询会起作用。但我同意,如果我们从Mongodbc获取词典,那么这是一种糟糕的做法。你可以用足够多的查询来分享你答案的基准吗?。这似乎很有效。谢谢。这看起来不错,但看起来很复杂。使用聚合框架必须有一种更简单的方法来实现这一点。为什么您需要在
“$project”
@jcmetz21下显示所有这些条目?我不认为这很复杂,我将添加解释,如果输出列表中的元素不需要按此精确顺序显示,但不会很简单,那么可能还有另一种方法可以这样做。元素需要按此精确顺序显示,这样看起来很好。谢谢@我的答案不仅看起来不错。这是最好的方法。在MongoDB 3.4中,可能还有另一种方法可以做到这一点。