2016-08-03 10 views
0

私はMySQLデータベースから一連の行を返すpythonプログラムと関数を持っています。これらの返された行は、タプルに含まれるIDのセットによってフィルタリングされます。次に、itertoolsとlist comprehensionを使用して、固定された制約のセットに適合する「組み合わせ」を形成します(各組み合わせの属性は、 "all equal"そのすべてのユニークな ")。動的制約数に対するitertoolsの組み合わせのフィルタリング

異なる数のIDに対して関数を動的にしたいのですが、返された行を動的にフィルタリングする方法がわかりません(入れ子にされたIF文を混乱させることなく)。 len(tuple_of_ids)に対して動的にするために、以下の関数のif /と条件を書き直す方法はありますか?

私はPython /コード開発に関してはまだ覚えていますので、助けていただければ幸いです!

私の現在(psuedo-)コード:

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

代わりのフィルタリングに追加することを忘れないでくださいする必要があることです* SQLクエリ*で、データベースをフィルタリングする必要がありますか? –

+0

それ以外の場合は、 'all()'と 'any()'関数を見てください。 –

+0

組み合わせを1回だけ繰り返し実行する場合は、効率を犠牲にする 'list(combination) 'を使わないでください。 –

答えて

1

マルタインコメントで述べたように、あなたはおそらく、より効率的に結合されている、SQLでフィルタリングを行うことを見てもよいです。フィルタリングはPythonで行われなければならない場合は、「すべて等しい」または「すべての異なる」チェックが簡単にセット理解して行うことができる:

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] 

これを行うとの唯一のオーバーヘッドがセットが破壊されていることです彼らの長さだけが必要とされるので、作成されるとすぐに。

キャストlistitertools.combinationsにドロップすることは、実際にはリストが必要ないためです。

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 

欠点は、あなたがWHERE`フィルタ、どうして `使用しない小規模な機能の多くを作成して、Pythonでリスト

関連する問題