2013-12-15 3 views
-1

Учитывая итерацию [A, B, C] и функция f(x) Я хочу, чтобы получить следующее:Учитывая повторяемость, как применить функцию во всех возможных сочетаниях?

[ A,  B,  C] 
[ A,  B, f(C)] 
[ A, f(B), C] 
[ A, f(B), f(C)] 
[f(A), B,  C] 
[f(A), B, f(C)] 
[f(A), f(B), C] 
[f(A), f(B), f(C)] 

К сожалению, я не нашел ничего подходящего в модуле itertools.

ответ

9
>>> from itertools import product 
>>> L = ["A", "B", "C"] 
>>> def f(c): return c.lower() 
... 
>>> fL = [f(x) for x in L] 
>>> for i in product(*zip(L, fL)): 
...  print i 
... 
('A', 'B', 'C') 
('A', 'B', 'c') 
('A', 'b', 'C') 
('A', 'b', 'c') 
('a', 'B', 'C') 
('a', 'B', 'c') 
('a', 'b', 'C') 
('a', 'b', 'c') 

Объяснение:

Вызов f для каждого элемента в L для создания fL

>>> fL 
['a', 'b', 'c'] 

Используйте zip застегнуть два списка в пар

>>> zip(L, fL) 
[('A', 'a'), ('B', 'b'), ('C', 'c')] 

Возьмите декартово произведение этих кортежей с помощью itertools.product

product(*zip(L, fL)) 

эквивалентно

product(*[('A', 'a'), ('B', 'b'), ('C', 'c')]) 

и что эквивалентно

product(('A', 'a'), ('B', 'b'), ('C', 'c')) 

цикл над этим продуктом, дает точно нужный нам результат.

+0

+1 ... Проклятье, это то, что я имел в виду, но не мог это кодировать ... Sigh .... – thefourtheye

+2

Это работает, но он вычисляет 'f' намного больше, чем необходимо, что может быть проблема в зависимости от того, насколько дорогой 'f'. – user2357112

+0

@ user2357112, см. Мое редактирование, адресованное этому –

1

Вы можете использовать itertools.combinations, как этот

def f(char): 
    return char.lower() 

iterable = ["A", "B", "C"] 
indices = range(len(iterable)) 
from itertools import combinations 
for i in range(len(iterable) + 1): 
    for items in combinations(indices, i): 
     print [f(iterable[j]) if j in items else iterable[j] for j in range(len(iterable))] 

Выход

['A', 'B', 'C'] 
['a', 'B', 'C'] 
['A', 'b', 'C'] 
['A', 'B', 'c'] 
['a', 'b', 'C'] 
['a', 'B', 'c'] 
['A', 'b', 'c'] 
['a', 'b', 'c'] 
+0

Выход должен содержать все элементы ввода, то есть: ['a', 'B', 'C'], а не только ['a']. – Kentzo

+0

@ Kentzo Пожалуйста, проверьте мой обновленный ответ. – thefourtheye

1
import itertools 
def func_combinations(f, l): 
    return itertools.product(*zip(l, map(f, l))) 

Демонстрация:

>>> for combo in func_combinations(str, range(3)): 
...  print combo 
... 
(0, 1, 2) 
(0, 1, '2') 
(0, '1', 2) 
(0, '1', '2') 
('0', 1, 2) 
('0', 1, '2') 
('0', '1', 2) 
('0', '1', '2') 

Эта функция сначала вычисляет f один раз для каждого элемента ввода. Затем он использует zip, чтобы повернуть ввод и список значений f в список пар ввода-вывода. Наконец, он использует itertools.product для создания каждого из возможных способов выбора ввода или вывода.

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