Множественный фильтр с использованием лямбда в питоне на rethinkdb?

Я пытаюсь отфильтровать объект массива внутри таблицы. Вот случай, когда я отфильтровал, и он отлично работает.

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()

Но мой вопрос в том, что я выполняю лямбда-операцию вручную, вместо этого я хочу, чтобы tagsLambda отфильтровывал все tags. Как мне это сделать?


person iraycd    schedule 09.02.2015    source источник


Ответы (2)


Я думаю, вы должны быть в состоянии сделать что-то вроде этого:

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/.

person gunn    schedule 09.02.2015

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.

Вторую лямбду можно заменить функцией.

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))  
person Nizam Mohamed    schedule 09.02.2015
comment
Чувак, это не сработает. Это точно должен быть оператор or. - person iraycd; 09.02.2015
comment
Не могли бы вы объяснить, что на самом деле делает этот код? Спасибо - person Paco; 09.02.2015
comment
@iraycd зачем тебе '|'? как вы можете фильтровать по одному тегу? я думаю '|' требуется только в том случае, если вы хотите фильтровать по нескольким тегам - person Nizam Mohamed; 09.02.2015
comment
@NizamMohamed Это то, чего я действительно хотел. Ваше решение отличное. Я думаю, ваше решение будет работать даже с & операциями. :) - person iraycd; 09.02.2015