Python实现多维列表的排列组合
最近在用python实现一个基础的数据挖掘功能,其中有一个场景是要将多个不同类型的因子,放到一起,并且根据因子的不同条件(正向排序、反向排序),列出所有可能的排列组合。
这里的类型记为 typelist=['type_a','type_b','type_c'...]
每一个类型下有多个因子:
type_a_list=['type_a_1'...]
type_b_list=['type_b_1','type_b_2'...]
type_c_list=['type_c_1','type_c_2','type_c_3'...]
这里每一个类型包含的因子数量不定,需动态加载
每一个因子包含至少2个取值条件(正向排序、反向排序)
最终期望得到的结果如:
[
[['type_a','type_a_1',True]],
[['type_a','type_a_1',False]],
[['type_b','type_b_1',True]],
[['type_b','type_b_1',False]],
[['type_b','type_b_2',True]],
[['type_b','type_b_2',False]],
[['type_a','type_a_1',True],['type_b','type_b_1',True]],
[['type_a','type_a_1',False],['type_b','type_b_1',True]],
[['type_a','type_a_1',False],['type_b','type_b_1',False]],
[['type_a','type_a_1',True],['type_b','type_b_1',False]],
[['type_a','type_a_1',True],['type_b','type_b_2',True]],
[['type_a','type_a_1',False],['type_b','type_b_2',True]],
[['type_a','type_a_1',False],['type_b','type_b_2',False]],
[['type_a','type_a_1',True],['type_b','type_b_2',False]],
[['type_a','type_b_1',True],['type_b','type_b_2',True]],
[['type_a','type_b_1',False],['type_b','type_b_2',True]],
[['type_a','type_b_1',True],['type_b','type_b_2',False]],
[['type_a','type_b_1',False],['type_b','type_b_2',False]],
......
]
python中有三个用于排列组合场景的函数:combinations、product、permutations,都属于itertools这个工具。
首先,对单个类型下的因子取所有组合,这里使用combinations函数。
combinations(iterable, r)方法用于创建一个迭代器,返回iterable中所有长度为r的子序列。对应上面的场景,可用于拆解每一个类型下的因子的所有组合,如:
y=1
while y<=len(type_b_list):
for i in combinations(type_b_list,y):
print(i)
y=y+1
例如对type_b_list=['type_b_1','type_b_2'] 将被拆解为
('type_b_1')
('type_b_2')
('type_b_1','type_b_2')
需要注意的是,这里返回的是tuple,而不是list。
接下来,要对多个类型下的因子所有组合放在一起叠加再取所有组合。这里可使用product函数:product(iterable_a,iterable_b),它用于对多个可迭代对象(如列表)求笛卡尔积。
对type_a类型和type_b类型的所有因子组合取笛卡尔积组合:
for i in product(comb_a,comb_b):
product_list.append(i)
即对('type_a_1')与('type_b_1'),('type_b_2'),('type_b_1','type_b_2')再取所有组合,最终获得:
('type_a_1')
('type_a_1'),('type_b_1')
('type_a_1'),('type_b_2')
('type_a_1'),('type_b_1','type_b_2')
('type_b_1')
('type_b_2')
('type_b_1','type_b_2')
('type_b_1'),('type_a_1')
('type_b_2'),('type_a_1')
('type_b_1','type_b_2'),('type_a_1')
('type_a_1'),('type_b_1'),('type_b_2')
('type_a_1'),('type_b_1'),('type_b_1','type_b_2')
('type_a_1'),('type_b_2'),('type_b_1','type_b_2')
('type_a_1'),('type_b_1'),('type_b_2'),('type_b_1','type_b_2')
......
返回值同样是tuple,后续需要添加进列表。
这里获得的结果,是有重复内容的,只是前后的排序不同,比如('type_a_1'),('type_b_1')与('type_b_1'),('type_a_1'),因此放到list中做进一步去重处理,采用sort方法对tuple执行统一排序,然后重新赋值,实现去重:
list_tmp=copy.deepcopy(product_list)
product_list=[]
for n in list_tmp:
n.sort()
if n not in product_list:
product_list.append(n)
这里之所以用deepcopy,是因为list对象的copy是浅层复制,当list为多维列表时,复制后的对象中的多维值部分修改,同样会修改到原对象的内容。
经过这一步后,已经获得了所有类型下所有因子的所有组合,但我们还需要进一步根据条件(正向排序,反向排序),再做一次条件叠加组合。
这里我把正向排序设为True(即 ascending=True),反向排序设为False(即 ascending=False),那么对应一个因子条件就存在至少两个条件组合,如('type_a_1',True)和('type_a_1',False)。
单个因子与条件的组合比较好处理,但是对多维因子组合与条件的叠加处理就比较麻烦了,比如('type_a_1'),('type_b_1'),('type_b_2'),('type_b_1','type_b_2') 叠加正反条件,产生结果:
[['type_a_1', True]],
[['type_b_1', True]],
[['type_b_2', True]],
[['type_a_1', True], ['type_b_1', True]],
[['type_a_1', True], ['type_b_2', True]],
[['type_b_1', True], ['type_b_2', True]],
[['type_a_1', True], ['type_b_1', True], ['type_b_2', True]],
[['type_a_1', False]],
[['type_b_1', False]],
[['type_b_2', False]],
[['type_a_1', False], ['type_b_1', True]],
[['type_a_1', True], ['type_b_1', False]],
[['type_a_1', False], ['type_b_1', False]],
[['type_a_1', False], ['type_b_2', True]],
[['type_a_1', True], ['type_b_2', False]],
[['type_a_1', False], ['type_b_2', False]],
[['type_b_1', False, ['type_b_2', True]],
[['type_b_1', True], ['type_b_2', False]],
[['type_b_1', False], ['type_b_2', False]],
[['type_a_1', False], ['type_b_1', True], ['type_b_2', True]],
[['type_a_1',True], ['type_b_1', False], ['type_b_2', True]],
[['type_a_1', True], ['type_b_1', True], ['type_b_2', False]],
[['type_a_1', False], ['type_b_1', False], ['type_b_2', True]],
[['type_a_1',True], ['type_b_1', False], ['type_b_2', False]],
[['type_a_1',False], ['type_b_1',True], ['type_b_2', False]],
[['type_a_1',False], ['type_b_1', False], ['type_b_2', False]],
......
这里又分作了三个子步骤处理:
第一步,将所有的原因子,都扩展成带正向条件的列表。如:
('type_a_1') => ['type_a_1', True]
('type_b_1','type_b_2') =>[['type_b_1',True],['type_b_2',True]]
第二步构造与因子同样维度的条件列表,然后对条件列表取所有排列组合,这里用到了permutations函数,它可以对集合或字符串进行排序或排列所有可能的组合。
factorBool= []+len(factorGroups)*[True]
m=0
while m<len(factorBool):
factorBool[m]=False
pResult=list(set(permutations(factorBool)))
m=m+1
第三步将因子列表按同纬度的条件列表组合,生成同样条件排列的组合
i=0
while i<len(pResult):
fGroup=copy.deepcopy(factorGroups)
j=0
while j<len(pResult[i]):
if pResult[i][j]==False:
fGroup[j][1]=False
else:
fGroup[j][1]=True
if fGroup not in factorResult:
factorResult.append(fGroup)
j=j+1
i=i+1
至此,经过以上处理后,终于得到了我想要的结果,即动态对多个不同类型下不确定个数因子,基于不同条件,生成出所有可能的排列组合项的结果集合。
拿到这个结果集后,我们可以按所有的因子组合来做自动运算(比如尺码+颜色+材质,对应获得的订单销量),进行想要的数据统计和分析,加上时间纬度,可以很容易的得出业务基于不同因子组合的运行特征,找出其中的关键因子。
本文来自博客园,作者:ik赵云,转载请注明原文链接:https://www.cnblogs.com/ikzhaoyun/p/17246063.html

浙公网安备 33010602011771号