在rethinkdb上使用python中的lambda进行多次过滤?

时间:2015-02-09 11:56:28

标签: python lambda rethinkdb rethinkdb-python

我正在尝试过滤表中的数组对象。这是我已经过滤并且完美运行的情况。

tags = ["school", "hollywood"]
tagsLambda =  lambda post: (post["tags"].contains(tags[0])) | (post["tags"].contains(tags[1]))
d = r.db("test").table("posts").filter(
    tagsLambda
).run()

但是,我的问题是我正在手动执行lambda操作,而是希望tagsLambda过滤所有tags。我该怎么做?

2 个答案:

答案 0 :(得分:3)

我认为你应该可以做这样的事情:

tags = ["school", "hollywood"]
r.db("test").table("posts").filter(
  lambda post: post["tags"].contains(lambda tag:
    r.expr(tags).contains(tag)
  )
).run(conn)

请参阅http://rethinkdb.com/api/python/contains/

答案 1 :(得分:1)

tags = ["school", "hollywood"]
tagsLambda =  lambda post: ( 
eval('|'.join(
           [r'(post["tags"].contains("' + tag + '"))' for tag in tags]
    ))
)
d = r.db("test").table("posts").filter(tagsLambda).run()  

[ r'post["tags"].contains("' + tag + '")' for tag in tags ]是列表理解。它为标记中的每个标记构建了一个字符串列表,如(post["tags"].contains("school"))'|'.join操作使用' |'从字符串列表构建一个字符串。在(post["tags"].contains("school")) | (post["tags"].contains("hollywood"))之间。 eval评估整个字符串。

使用reduce作为

可以简化上述代码
tags = ["school", "hollywood"]
tagsLambda =  lambda post:
    reduce(lambda x,y: x | y, [ post["tags"].contains(tag) for tag in tags])

d = r.db("test").table("posts").filter(tagsLambda).run()  

对于Python 3,' functools'必须导入才能使用reduce并将reduce替换为functools.reduce

第二个lambda可以用函数替换。

import operator as op
reduce(op.or_, [ post["tags"].contains(tag) for tag in tags])  

用户生成器以获得更好的结果。

reduce(op.or_, ( post["tags"].contains(tag) for tag in tags))