Python学習7日目～内包表記～

## 内包表記
for文やif文に似た使い方でリスト、辞書、集合に格納する値を生成することができる
何よりプログラムを簡潔に出来るという点でコードの可読性が高くなる

~~~Python:comp.py
# 0から9までの整数を2乗した値を格納したリストを作成する

a = []
for x in range(10):
    a.append(x*x)
print(a)
~~~
~~~:実行結果
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
~~~

これまで学習した内容だと上記のような書き方になる
これを内包表記で書くと以下の通り

~~~Python:comp.py
# 0から9までの整数を2乗した値を格納したリストを作成する
print([x*x for x in range(10)])

# リストの内包表記は以下の通り
[式 for 変数 in イテラブル]
~~~
~~~:実行結果
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
~~~

集合の内包表記もリストと考え方は同じ

~~~Python:comp.py
# 0から9までの整数を2乗した値を格納した集合を作成する
print({x*x for x in range(10)})
~~~
~~~:実行結果
{0, 1, 64, 4, 36, 9, 16, 49, 81, 25}
~~~

集合は格納された順番と実行の際の要素を表示する順番は一致しないので、ぐちゃぐちゃな順番になっている

辞書の場合少し記述が変わる
理由としては辞書はキーと値が必要なため
今回はキーを2乗する前の数値、値を2乗の結果にする

~~~Python:comp.py
# 0から9までの整数を2乗した値を格納した辞書を作成する
print({x: x*x for x in range(10)})

#　書き方
{キーの式: 値の式 for 変数 in イテラブル}
~~~
~~~:実行結果
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
~~~

## 内包表記で多重ループを表現する

~~~Python:comp.py
# 九九の結果をリストに格納する
a = []
for x in range(1,10):
    for y in range(1,10):
        a.append(x*y)
print(a)
~~~
~~~:実行結果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 4, 6, 8, 10, 12, 14, 16, 18, 3, 6, 9, 12, 15, 18, 21, 24, 27, 4, 8, 12, 16, 20, 24, 28, 32, 36, 5, 10, 15, 20, 25, 30, 35, 40, 45, 6, 12, 18, 24, 30, 36, 42, 48, 54, 7, 14, 21, 28, 35, 42, 49, 56, 63, 8, 16, 24, 32, 40, 48, 56, 64, 72, 9, 18, 27, 36, 45, 54, 63, 72, 81]
~~~

これを内包表記で表現する
    
~~~Python:comp.py
# 九九の結果をリストに格納する
print([x*y for x in range(1,10) for y in range(1,10)])
~~~
~~~:実行結果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 4, 6, 8, 10, 12, 14, 16, 18, 3, 6, 9, 12, 15, 18, 21, 24, 27, 4, 8, 12, 16, 20, 24, 28, 32, 36, 5, 10, 15, 20, 25, 30, 35, 40, 45, 6, 12, 18, 24, 30, 36, 42, 48, 54, 7, 14, 21, 28, 35, 42, 49, 56, 63, 8, 16, 24, 32, 40, 48, 56, 64, 72, 9, 18, 27, 36, 45, 54, 63, 72, 81]
~~~

多重ループであっても基本的には特に変わらない

集合も大して変わらないので、辞書にして九九の式をキーに結果を値に入れる

~~~Python:comp.py
# 九九の結果を辞書に格納する
print({str(x)+'*'+str(y): x*y for x in range(1,10) for y in range(1,10)})
~~~
~~~:実行結果
{'1*1': 1, '1*2': 2, '1*3': 3, '1*4': 4, '1*5': 5, '1*6': 6, '1*7': 7, '1*8': 8, '1*9': 9, '2*1': 2, '2*2': 4, '2*3': 6, '2*4': 8, '2*5': 10, '2*6': 12, '2*7': 14, '2*8': 16, '2*9': 18, '3*1': 3, '3*2': 6, '3*3': 9, '3*4': 12, '3*5': 15, '3*6': 18, '3*7': 21, '3*8': 24, '3*9': 27, '4*1': 4, '4*2': 8, '4*3': 12, '4*4': 16, '4*5': 20, '4*6': 24, '4*7': 28, '4*8': 32, '4*9': 36, '5*1': 5, '5*2': 10, '5*3': 15, '5*4': 20, '5*5': 25, '5*6': 30, '5*7': 35, '5*8': 40, '5*9': 45, '6*1': 6, '6*2': 12, '6*3': 18, '6*4': 24, '6*5': 30, '6*6': 36, '6*7': 42, '6*8': 48, '6*9': 54, '7*1': 7, '7*2': 14, '7*3': 21, '7*4': 28, '7*5': 35, '7*6': 42, '7*7': 49, '7*8': 56, '7*9': 63, '8*1': 8, '8*2': 16, '8*3': 24, '8*4': 32, '8*5': 40, '8*6': 48, '8*7': 56, '8*8': 64, '8*9': 72, '9*1': 9, '9*2': 18, '9*3': 27, '9*4': 36, '9*5': 45, '9*6': 54, '9*7': 63, '9*8': 72, '9*9': 81}
~~~

## 内包表記とifを組み合わせる

~~~Python:comp.py
# 0から19までの数値のうち2の倍数でも3の倍数でもない値をリストに格納する
print([x for x in range(20) if x%2 and x%3])
~~~
~~~:実行結果
[1, 5, 7, 11, 13, 17, 19]
~~~

## 内包表記と条件式を組み合いれたわせる
内包表記と条件式(**三項演算子**)を組み合わせると便利(らしい)

~~~Python:fizzbuzz.py
# Fizz Buzzゲームを15までやる
# 3の倍数の時に'Fizz'、5の倍数の時に'Buzz'、15の倍数の時に'Fizz Buzz'と言う

a = []
for x in range(1,16):
    if x%15 == 0:
        a.append('Fizz Buzz')
    elif x%5 == 0:
        a.append('Buzz')
    elif x%3 == 0:
        a.append('Fizz')
    else:
        a.append(x)
print(a)
~~~
~~~:実行結果
[1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz', 11, 'Fizz', 13, 14, 'Fizz Buzz']
~~~

これはいつも通りの書き方
これを内包表記で記載する

~~~Python:fizzbuzz.py
# Fizz Buzzゲームを15までやる
# 3の倍数の時に'Fizz'、5の倍数の時に'Buzz'、15の倍数の時に'Fizz Buzz'と言う
print(['Fizz Buzz' if x%15 == 0 else 'Buzz' if x%5 == 0 else 'Fizz' if x%3 == 0 else x for x in range(1,16)])
~~~
~~~:実行結果
[1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz', 11, 'Fizz', 13, 14, 'Fizz Buzz']
~~~

とこのように内包表記を使うことでリスト・辞書・集合に格納する系のプログラムを簡単に書くことができる
ちなみにリストを変数に入れるときは

~~~Python:fizzbuzz.py
# Fizz Buzzゲームを15までやる
# 3の倍数の時に'Fizz'、5の倍数の時に'Buzz'、15の倍数の時に'Fizz Buzz'と言う
a = ['Fizz Buzz' if x%15 == 0 else 'Buzz' if x%5 == 0 else 'Fizz' if x%3 == 0 else x for x in range(1,16)]
~~~

これでいける
かなり便利になる