スプレッドシートで各要素の掛け合わせの表を作る (Python)

## 前提条件

次のような Python ディクショナリ型 の値をスプレッドシートに表の形で記述する場合。

```python
    pattern = {
        'エリア': ['日本', 'アメリカ', 'イギリス'],
        '性別': ['男', '女'],
        '身長': ['100cm以上', '100cm未満']
    }
```

### 環境

* Python 3.7.6
* Linux


## 掛け合わせ表の作成 (直積)

スプレッドシートで次のような各要素を掛け合わせた表を作りたい場合、

|  | エリア | 性別 | 身長 |
|:--|:--|:--|:--|
| 1 | 日本 | 男 | 100cm以上 |
| 2 | 日本 | 男 | 100cm未満 |
| 3 | 日本 | 女 | 100cm以上 |
| 4 | 日本 | 女 | 100cm未満 |
| 5 | アメリカ | 男 | 100cm以上 |
| 6 | アメリカ | 男 | 100cm未満 |
| 7 | アメリカ | 女 | 100cm以上 |
| 8 | アメリカ | 女 | 100cm未満 |
| 9 | イギリス | 男 | 100cm以上 |
| 10 | イギリス | 男 | 100cm未満 |
| 11 | イギリス | 女 | 100cm以上 |
| 12 | イギリス | 女 | 100cm未満 |

Python で次のように書くと、カンマ区切りのものが出力されるので

```python
from itertools import product

if __name__ == '__main__':
    pattern = {
        'エリア': ['日本', 'アメリカ', 'イギリス'],
        '性別': ['男', '女'],
        '身長': ['100cm以上', '100cm未満']
    }
    delimiter = ','
    result = delimiter + delimiter.join(pattern.keys()) + '\n'
    i = 0
    for item in product(*pattern.values()):
        i += 1
        result += str(i) + delimiter + delimiter.join(item) + '\n'
    print(result)
```

それをスプレッドシートに貼り付けるとうまい具合に表ができます。

```csv
,エリア,性別,身長
1,日本,男,100cm以上
2,日本,男,100cm未満
3,日本,女,100cm以上
4,日本,女,100cm未満
5,アメリカ,男,100cm以上
6,アメリカ,男,100cm未満
7,アメリカ,女,100cm以上
8,アメリカ,女,100cm未満
9,イギリス,男,100cm以上
10,イギリス,男,100cm未満
11,イギリス,女,100cm以上
12,イギリス,女,100cm未満
```

### 補足

* `itertools.product` を使って、 複数のリストの掛け合わせを作っています。 この関数は可変長引数ですから、 `*pattern.values()` と書いてリストを展開する書き方にしています。
* `for` の中で使う `i` は `emumerate` を使って作ることもできます。 次のコードでは `enumerate` を使っています。

## 分類項目表の作成

上の掛け合わせ表の各項目とその値について次のような表を作りたい場合

| 項目 | 値 |
|:--|:--|
| エリア | 日本 |
|  | アメリカ |
|  | イギリス |
| 性別 | 男 |
|  | 女 |
| 身長 | 100cm以上 |
|  | 100cm未満 |

Python で次のように書くと、カンマ区切りのものが出力されるので

```python
if __name__ == '__main__':
    pattern = {
        'エリア': ['日本', 'アメリカ', 'イギリス'],
        '性別': ['男', '女'],
        '身長': ['100cm以上', '100cm未満']
    }
    delimiter = ','
    result = ''
    for key, value in pattern.items():
        for index, item in enumerate(value):
            if index == 0:
                result += key
            result += delimiter + item + '\n'
    print(result)
```

それをスプレッドシートに貼り付けるとうまい具合に表ができます。

```csv
エリア,日本
,アメリカ
,イギリス
性別,男
,女
身長,100cm以上
,100cm未満
```

## まとめたコード

これを対話型で進められるひとつのPythonファイルにすると次のようになります・

```python
from itertools import product

def get_input(default: str = ''):
    value: str = input().rstrip("\n")
    if value:
        return value
    return default

def configure():
    print("""
Please configure
    delimiter [,]:
""")
    delimiter = get_input(',')

    print(f"""
    prefix:
    """)
    prefix = get_input()

    print(f"""
    suffix:
    """)
    suffix = get_input()
    return delimiter, prefix, suffix

def print_product_table(pattern: dict, delimiter: str, prefix: str, suffix: str):
    result = prefix + delimiter + delimiter.join(pattern.keys()) + suffix + '\n'
    i = 0
    for item in product(*pattern.values()):
        i += 1
        result += prefix + str(i) + delimiter + delimiter.join(item) + suffix + '\n'
    print(result)

def print_category_key_value(pattern, delimiter, prefix, suffix):
    result = ''
    for key, value in pattern.items():
        for index, item in enumerate(value):
            line = prefix
            if index == 0:
                line += key
            line += delimiter + item + suffix
            result += line.strip() + '\n'
    print(result)

if __name__ == '__main__':
    pattern = {
        'エリア': ['日本', 'アメリカ', 'イギリス'],
        '性別': ['男', '女'],
        '身長': ['100cm以上', '100cm未満']
    }

    print_pattern: int = None
    while True:
        print("""
Print dict structure.

Enter print pattern:
    1. Product table
    2. Category key-value
        """)
        print_pattern = int(get_input())
        if print_pattern in [1, 2]:
            break;

    delimiter, prefix, suffix = configure()

    if print_pattern == 1:
        print_product_table(pattern, delimiter, prefix, suffix)
    elif print_pattern == 2:
        print_category_key_value(pattern, delimiter, prefix, suffix)
```

## その他

<dl>
  <dt>なぜ Python なのか</dt><dd>ちょうどそのとき Python 使って作業していたからです。</dd>
</dl>