过滤迭代工具组合以获得动态数量的约束

时间:2016-08-03 18:12:12

标签: python python-2.7

我有python程序和函数,它从我的MySQL数据库返回一系列行。这些返回的行由元组中包含的一组ID过滤,然后我使用itertools和list comprehension来形成符合一组固定约束的“组合”(每个组合的属性必须是“全部相等”或“所有独特的“在这种组合中”。

我想为不同数量的ID使函数动态,但我不确定如何动态过滤返回的行(没有乱七八糟的嵌套IF语句)。有没有办法可以在下面的函数中重写if /和条件,使它们为len(tuple_of_ids)动态化?

在python /代码开发方面,我仍然是一个学习者,所以任何帮助都会受到赞赏!

我当前的(假的)代码:

import itertools

def get_valid_combinations(tuple_of_ids):

    data = get_filtered_data_from_database(valid_ids=tuple_of_ids)

    # (row1, row2, row3) assumes that the tuple_of_ids has len=3. If tuple_of_ids had 4 members I'd need (row1, row2, row3, row4) etc
    valid_combinations = [(row1, row2, row3) for row1, row2, row3 in list(itertools.combinations(data, 3))
                                if ((row1.Age == row2.Age)              # All items in combination have same Age
                                    and (row2.Age == row3.Age))

                                and ((row1.School != row2.School)
                                     and (row2.School != row3.School)
                                     and (row1.School != row3.School))      # All items in combination have different School
                ]
                # ...etc (i.e. there may be multiple filtering criteria, but always either ("all equal" or "all different")

    return valid_combinations

ids_to_search_for = ('C00001', 'C00002', 'C00003')
get_valid_combinations(tuple_of_ids = ids_to_search_for)

>>> [(<database_row_object_1>, <database_row_object_2>, <database_row_object_3>), (<database_row_object_x>, <database_row_object_y>, <database_row_object_z>),...]

2 个答案:

答案 0 :(得分:1)

正如Martijn在评论中所说,你可能会考虑在SQL中进行过滤,这可能会更有效率。如果过滤必须在Python中完成,那么<​​em>“all equal”或“all different”检查可以通过集合理解轻松完成:

length = len(tuple_of_ids)
valid_combinations = [tup for tup in itertools.combinations(data, length)
                              if len({r.Age for r in tup}) == 1
                              and len({r.School for r in tup}) == length]

执行此操作的唯一开销是,一旦创建集就会被销毁,因为只需要它们的长度。

在旁注中,您可以将{em>强制转换放到list itertools.combinations,因为您实际上并不需要该列表。

答案 1 :(得分:0)

我认为通过引用传递函数是一种非常类似于在代码中轻松添加或删除约束的方法。这是一个人为的例子:

#Just an example class
class Person(object):
    __slots__ = ["age","height","weight"]
    def __init__(self,age,height,weight):
        self.age = age
        self.height = height
        self.weight = weight
​
#Function to try all tests
def test_people(people,tests):
    test_results = [test(people) for test in tests]
    print "Passed all tests:",all(test_results)
    print "Passed at least one:",any(test_results)

#Testing functions to be passed into the test_people
def first_lighter_than_second(people):
    p1 = people[0]
    p2 = people[1]
    return True if p1.weight < p2.weight else False
def third_older_than_first(people):
    p1 = people[0]
    p3 = people[2]
    return True if p3.age > p1.age else False
​
#Building people list
p1 = Person(24,182.1,90.5)
p2 = Person(50,170.4,83)
p3 = Person(62,150.3,67)
people = [p1,p2,p3]
​
#Building list of test functions
tests = []
tests.append(first_lighter_than_second)
tests.append(third_older_than_first)
​
#Try all tests
test_people(people,tests)

#Output
Passed all tests: False
Passed at least one: True

缺点是你需要创建许多小函数并记得将它们添加到列表中