trsing’s diary

勉強、読んだ本、仕事で調べたこととかのメモ。

組み合わせの書き出し

やりたいこと

Excelで組み合わせを記述し、それを書き出す
例:
条件1={A1,A2}、 条件2={B1,B2}、 条件3={C1,C2}
のとき
条件1x条件2x条件3={(A1,B1,C1),(A1,B1,C2),(A1,B2,C1),(A1,B2,C2),(A2,B1,C1),(A2,B1,C2),(A2,B2,C1),(A2,B2,C2)}
を表示したい

コード

※この記事書いてるときに気づいたけど条件読み込んだ後は直積(product)を使えば良かったみたい…

itertools --- 効率的なループ実行のためのイテレータ生成関数 — Python 3.7.2 ドキュメント

import xlrd
 
#  組み合わせ項目の表示
def printcmb(ren, pt, lst):
    if len(lst)<pt+1 or not lst[pt]:
        print(ren)
        return
    for tui in lst[pt]:
        printcmb(ren+tui+'_',pt+1,lst)
 
#  組み合わせ項目のリストを作成する
def makelst(lst2d, br, lxlsvl):
    mr = br
    flg = False
    rowsize = len(lst2d)
    colsize = len(lst2d[0])
    for c in range(colsize):
        lvl = []
        for r in range(br,rowsize):
            vl = lst2d[r][c]
            #  空の場合、左隣が空じゃない場合   
            if vl=='' or (0<c and mr<r and ''!= lst2d[r][c-1]):
                break
            lvl.append(vl)
            flg = True
            mr = max(mr,r)
            #  右隣りが空で右下が空で無い場合   
            if c<colsize-1 and r<rowsize-1 and''==lst2d[r][c+1] and ''!=lst2d[r+1][c+1]:
                break
        if flg:
            if(len(lxlsvl)<c+1):
                lxlsvl.append(lvl)
            else:
                lxlsvl[c] = lvl
    return mr, lxlsvl
 
wb = xlrd.open_workbook('hoge.xlsx')
for sheet in wb.sheets():
    #  Sheetの値を二次元配列に。floatがあればintにして文字列に
    sheetvalues = [sheet.row_values(x) for x in range(sheet.nrows)]
    sheetvalues = [[str(int(n)) if isinstance(n,float) else str(n) for n in lst] for lst in sheetvalues]

    lxlsvl = []
    maxr = 0
    for nidx in range(len(sheetvalues)):
        maxr, lxlsvl = makelst(sheetvalues, maxr, lxlsvl)
        maxr += 1
        printcmb('', 0, lxlsvl)
        if len(sheetvalues)<=maxr:
            break;
    print('\n')

#  ファイルに書き出す場合printの前後に
#  import sys 
#  sys.stdout=open('result.txt','w')
#  sys.stdout.close()
#  sys.stdout=sys.__stdout__
入力

{A1,A2}x{B1,B2,B3,B4}x{C1,C2,C3}、 {A1,A2}x{BB1}x{CC1,CC2}が欲しい場合excelのシートに

A B C
1 A1 B1 C1
2 A2 B2 C2
3 B3
4 BB1 CC1
5 CC2
出力
A1_B1_C1_  
A1_B1_C2_  
A1_B2_C1_  
A1_B2_C2_  
A1_B3_C1_  
A1_B3_C2_  
A2_B1_C1_  
A2_B1_C2_  
A2_B2_C1_  
A2_B2_C2_  
A2_B3_C1_  
A2_B3_C2_  
A1_BB1_CC1_  
A1_BB1_CC2_  
A2_BB1_CC1_  
A2_BB1_CC2_  

背景

条件1がA1、条件2がB1、条件3がC1の場合のパラメータ
みたいなのを大量に記述しなきゃいけなくなったので。一つずつ手書きなんてしてらんないよと。パラメータ数四桁はいきますね。ええ。

直積使う場合の例

b = ['B1','B2']
c = ['C1','C2']
a = ['A1','A2']
list(itertools.product(a,b,c))
#出力
[('A1', 'B1', 'C1'),
 ('A1', 'B1', 'C2'),
 ('A1', 'B2', 'C1'),
 ('A1', 'B2', 'C2'),
 ('A2', 'B1', 'C1'),
 ('A2', 'B1', 'C2'),
 ('A2', 'B2', 'C1'),
 ('A2', 'B2', 'C2')]