2014-12-11 102 views
0

假设foo是一个列表或其他迭代器。我想要一些东西,使我可以(伪代码):每个循环的内循环数量未定义

for i in foo 
    for j in foo - [i] 
     for k in foo - [i, j] 
      ... 
       for some_var in foo - [i, j, k, ...]//only one value left in foo 
        do_something(some_args) 

有没有办法在python中做到这一点?我可以在一个循环中做到这一点,我必须使用递归,或者我必须(只有在没有其他方式)的代码对象?

+2

对于foo中的j是什么意思? 'foo'显然是一个枚举,所以我不知道'foo - i'是什么。 – ganbustein 2014-12-11 03:02:12

+0

好吧,我们知道'foo'是可迭代的,并且假设列表类行为,'i'是'foo'中的一个项 - 我们无法猜测'foo - i'的含义。 – 2014-12-11 03:04:42

+0

对不起,我会更清楚。 – tox123 2014-12-11 03:09:08

回答

1

你的问题与combinatorics有关。具体笛卡尔产品。

没有递归,你需要知道你要运行多少个循环的嵌套。但是,您不需要提前知道这些信息。只要你能动态地得到它就没问题。

考虑我的回购协议的一个采取这样的代码:https://github.com/Erotemic/utool/blob/next/utool/util_dict.py

from itertools import product 
import six 

varied_dict = { 
'logdist_weight': [0.0, 1.0], 
'pipeline_root': ['vsmany'], 
'sv_on': [True, False, None] 
} 

def all_dict_combinations(varied_dict): 
     tups_list = [[(key, val) for val in val_list] 
      for (key, val_list) in six.iteritems(varied_dict)] 
     dict_list = [dict(tups) for tups in product(*tups_list)] 
     return dict_list 

dict_list = all_dict_combinations(varied_dict) 

运行此代码将导致dict_list是

[ 
     {'pipeline_root': 'vsmany', 'sv_on': True, 'logdist_weight': 0.0}, 
     {'pipeline_root': 'vsmany', 'sv_on': True, 'logdist_weight': 1.0}, 
     {'pipeline_root': 'vsmany', 'sv_on': False, 'logdist_weight': 0.0}, 
     {'pipeline_root': 'vsmany', 'sv_on': False, 'logdist_weight': 1.0}, 
     {'pipeline_root': 'vsmany', 'sv_on': None, 'logdist_weight': 0.0}, 
     {'pipeline_root': 'vsmany', 'sv_on': None, 'logdist_weight': 1.0}, 
    ] 

,然后你可以写代码像

for some_vars in dict_list: 
     do_something(some_vars) 

如果你想列举每个值foo可以采取我称之为vary_dict的每个嵌套级别,然后你可以得到你的问题的解决方案。另请注意,vary_dict可以动态构建,并且不一定是字典。如果您修改了我的代码,您可以使用其他结构的列表轻松地指定值。

上述代码中的魔术归结为itertools.product函数的使用。我建议你看看那个。 https://docs.python.org/2/library/itertools.html#itertools.product