如何在Python中实现高效的过滤逻辑?

Chr*_*ung 7 python sqlite logic pyqt filter

我正在尝试创建一个存储的程序

  1. 水果名称
  2. 水果类型
  3. 水果颜色
  4. 水果大小

并根据要求将它们显示给用户.将为用户提供预定义的选择以供选择.像这样的东西:

在此输入图像描述

我的数据库表是这样的:

在此输入图像描述

现在,我正在尝试实现一个允许用户选择的过滤功能

  • 水果类型
  • 水果颜色
  • 水果大小

并且它将给出Fruit Names具有上述属性的所有内容.但现在,我有一个额外的选项,"全部".

在此输入图像描述

假设我已经查询了所有水果的数据并将它们存储在字典中,如下所示:

myfruits = { 'apple':('fleshy','red','medium'),
            'orange':('fleshy','orange','medium'),
             'peanut':('dry','red','small'),...}
Run Code Online (Sandbox Code Playgroud)

如何获取具有用户选择的三个属性的水果名称列表?(例如,如果用户选择"肉质"类型,"全部"颜色,"全部"大小 - 它应该返回['apple','orange'].)

我曾想过使用if语句,但随着属性数量的增加,我将不得不写出这么多行,ifelse我认为这些行是不可行的.

我在32位Windows XP SP3上使用Python 2.7和PyQt 4以及SQLite 3数据库.

Mar*_*ers 10

我在这里使用SQLAlchemy来处理数据库层,要么将其用作ORM,要么只生成SQL表达式.

这使您可以动态生成过滤器; 您可以遍历过滤器,并且特定过滤器尚未设置为"全部",请通过它限制查询.

使用SQLAlchemy生成SQL表达式将类似于:

from sqlalchemy.sql import select

fruit_query = select([fruits])
for filtername in ui_filters:
    filtervalue = obtain_filter_value_for(filtername)
    if filtervalue != 'All':
        fruit_query = fruit_query.where(filtername == filtervalue)
Run Code Online (Sandbox Code Playgroud)

另一种方法是WHERE手动生成子句:

query = 'SELECT * FROM fruits'
params = []
whereclauses = []

for filtername in ui_filters:
    filtervalue = obtain_filter_value_for(filtername)
    if filtervalue != 'All':
        whereclauses.append('{} = ?'.format(filtername))
        params.append(filtervalue)

if whereclauses:
    query = '{} WHERE {}'.format(query, ' AND '.join(whereclauses))

cursor.execute(query, params)
Run Code Online (Sandbox Code Playgroud)

但请注意,SQLAlchemy表达式引擎更灵活,更不容易出错.很快你就会想(在范围内,文本搜索的搜索,结合in"或"表达式过滤器)添加更复杂的过滤器和SQLAlchemy的可以产生表达式很多简单的,真的.


Pie*_*pin 3

如果您已经查询出所有数据,一个简单的方法就是使用该filter函数:

def predicate(fruit_type, fruit_color, fruit_size):
    def _predicate(fruit):
        if not fruit_type == 'All' and not fruit_type == fruit[1][0]:
            return False
        if not fruit_color == 'All' and not fruit_color == fruit[1][1]:
            return False
        if not fruit_size == 'All' and not fruit_size == fruit[1][2]:
            return False
        return True
    return _predicate

query_type = 'All'
query_color = 'All'
query_size = 'All'
myfruits = {}
my_filtered_fruit = list(filter(predicate(query_type, query_color, query_size), myfruits.items()))
Run Code Online (Sandbox Code Playgroud)

另一种方法是定义一个Predicate具有视图(过滤器的名称)和关联的过滤器函数的对象:

class Predicate:
    def __init__(self, predicate, view):
        self.predicate = predicate
        self.view = view

# Creation of the predicates :
all_color = Predicate(lambda fruit: True, 'All colors')
red_color = Predicate(lambda fruit: fruit[2] == 'red')
# ...

# Then you have to generate your select form. I don't remember exactly the PyQt4 doc but it's not the harder part.

predicates = getAllSelected() # I guess you know how to get this kind of function

myfruits = {}
my_filtered_fruits = myfruits.items()
for pred in predicates:
    my_filtered_fruit = filter(lambda x: pred(x[1]), my_filtered_fruit)
my_filtered_fruit = list(my_filtered_fruit)
Run Code Online (Sandbox Code Playgroud)