2014-01-30 3 views
2

У меня есть функция, которая принимает удовольствие несколько параметров p0, p1, .. Для каждого параметра я дать список возможных значений:Продукт Python itertools, но условный?

p0_list = ['a','b','c'] 
p1_list = [5,100] 

теперь я могу назвать свою функцию для каждой комбинации p0, p1

for i in itertools.product(*[p0,p1]): 
    print fun(i) 

Теперь возникает проблема: что, если я уже знаю, что параметр p1 влияет только на результат забавы, если p0 является «a» или «c»? В этом случае я нужен мой список комбинаций параметров выглядеть следующим образом:

[('a', 5), ('a',100), ('b', 5), ('c',5), ('c', 100)] 

So («B», 100) просто опущена, так как это было бы ненужной оценка удовольствия.

Мое окончательное решение:

param_lists = [['p0', ['a','b','c']],['p1, [5,100]]] 
l = itertools.product(*[x[1] for x in param_lists]) 
l = [x for x in l if not x[0] == 'b' or x[1]==5] 

Я использовал этот подход для 5 параметров и различных условий и она отлично работает. Это довольно легко читать. Этот код вдохновлен ответами Corley Brigmans и nmcleans.

+0

Я бы лично просто воспользовался вашими вызовами функций и позвонил им с каждой комбинацией. – roippi

+0

Для этого потребуется указать, какие комбинации дают одинаковые результаты, что дало бы мне возможность удалить эти комбинации. Правильно? – HeinzKurt

ответ

1

Вы можете сгенерировать его, а затем подавить «дубликаты». Но, вероятно, просто лучше произвести отдельно:

p0_list = ['a', 'b', 'c'] 
p0_noarg1 = ['b'] 
sp0_noarg1 = set(p0_noarg1) 
p0_arg1 = [x for x in p0_list if x not in sp0_noarg1] 
p1_list = [5, 100] 

total_list = [x for x in itertools.product(p0_arg1, p1_list)] + [x for x in itertools.product(p0_noarg1, p1_list[:1])] 
+0

Спасибо, что работает! Но, конечно, решение является неприятным при работе с параметрами 2+. Однако я не думаю, что могу ожидать более элегантное решение, так как проблема настолько противная. – HeinzKurt

+0

Можете ли вы рассказать мне, почему вы используете set() здесь? Я попробовал, и он работает без set(). – HeinzKurt

+0

Поиск элемента в 'set' (aka hashtable) - это операция O (1) - это более или менее фиксированное время - вы вычисляете индекс, где он должен быть, смотрите там, и он либо там, либо нет (игнорирование хеш-столкновения, которые должны быть редкими). Поиск элемента в «списке» - это операция O (n) - вы должны каждый раз смотреть на каждый элемент, чтобы определить, что этого элемента нет. Во-первых, для создания набора требуется немного времени, но это почти всегда стоит того. –

3

Вот общая функция фильтра, которая могла бы работать для этого:

def without_duplicate_item(groups, index, item): 
    seen = False 
    for group in groups: 
     if group[index] == item: 
      if seen: 
       continue 
      seen = True 
     yield group 

Использование:

param_groups = itertools.product(*[p0_list, p1_list]) 

param_groups = without_duplicate_item(param_groups, 0, "b") 

Вы, конечно, можете продолжать добавлять фильтры разные параметры. Это должно быть достаточно экономичным по сравнению с хранением предыдущих вызовов, поскольку оно по существу хранит только одно логическое значение seen на фильтр.

Смежные вопросы