我在名为favoriteColors
的MongoDB集合中有以下4个词典:
{ "name" : "Johnny", "color" : "green" }
{ "name" : "Steve", "color" : "blue" },
{ "name" : "Ben", "color" : "red" },
{ "name" : "Timmy", "color" : "cyan" }
我试图创建一个与不同有序列表匹配的ORDERED颜色值列表。
例如,如果我有列表["Johnny", "Steve", "Ben", "Johnny"]
,则新列表将["green", "blue", "red", "green"]
。
如果我有列表["Steve", "Steve", "Ben", "Ben", "Johnny"]
,则新列表将为["blue", "blue", "red", "red", "green"]
。
使用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"]
答案 0 :(得分:1)
实际上,我们可以使用聚合框架和客户端处理来有效地执行此操作。
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'}}}
])
因为我们$group
是None,我们的光标包含一个文档,我们可以使用next
来检索它。事实上,我们可以通过print(list(cursor))
>>> import pprint
>>> pprint.pprint(list(cursor))
[{'_id': None,
'data': [['green', None, None, 'green'],
[None, 'blue', None, None],
[None, None, 'red', None]]}]
从这里,我们需要解包"数据"使用zip
的文档中的字段,使用chain.from_iterable
对输入进行链接,并过滤掉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']
答案 1 :(得分:0)
如果数据集很小,您可以将dicts合并为一个新的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
上调用Collection
方法。答案相应更新。
答案 2 :(得分:0)
您还可以根据当前的代码创建新的dict
,其中dict["name"]
的每个值都与dict["color"]
值相关联。
例如:新词典将如下:
{"Jhonny": "green", "Steve": "blue"}
你可以使用类似下面例子的函数来接受许多参数并返回所需的列表(如果输入列表中有任何名称在默认值中不存在,它还会附加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']
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', None, 'red', 'red', 'green', None]