概要
この記事では、Pythonにおける配列の内包表記法をまとめている。
それに加え、比較的覚えにくい条件式(ifのみ、if-elseの違い)の記法の考え方を示し、内包表記のメリットとデメリットを考察する。
内包表記による配列の作成
基本
例
0から4までの数字を配列に格納する。
a = [i for i in range(5)]
# a = [0, 1, 2, 3, 4]
等価なコード
a = []
for i in range(5):
a.append(i)
forを重ねる
例
10の位を0から3まで、1の位を4から7まで変化させ、数字を配列に格納する。
a = [i*10+j for i in range(4) for j in range(4, 8)]
# a = [4, 5, 6, 7, 14, 15, 16, 17, 24, 25, 26, 27, 34, 35, 36, 37]
等価なコード
a = []
for i in range(4):
for j in range(4, 8):
a.append(i*10+j)
条件分岐(ifのみ)
例
0から4までのうち、偶数を配列に格納する。
a = [i for i in range(5) if i % 2 == 0]
# a = [0, 2, 4]
等価なコード
a = []
for i in range(5):
if i % 2 == 0:
a.append(i)
条件分岐(if, else)
例
0から4までのうち、偶数をそのまま、奇数を10倍して配列に格納する。
a = [i if i % 2 == 0 else i*10 for i in range(5)]
# a = [0, 10, 2, 30, 4]
等価なコード
a = []
for i in range(5):
if i % 2 == 0:
a.append(i)
else:
a.append(i*10)
複合形
10の位を0から3まで、1の位を4から7まで変化させる。ただし、10の位が奇数のときは代わりに100の位とし、さらに、1の位が偶数の場合のみ数字を配列に格納する。
a = [i*10+j if i % 2 == 0 else i*100+j for i in range(4) for j in range(4, 8) if j % 2 == 0]
# a = [4, 6, 104, 106, 24, 26, 304, 306]
等価なコード
a = []
for i in range(4):
for j in range(4, 7):
if j % 2 == 0:
if i % 2 == 0:
a.append(i*10+j)
else:
a.append(i*100+j)
条件分岐の覚え方・考え方(ifのみ or if-else)
# ifのみ
a = [i for i in range(5) if i % 2 == 0]
# if-else
a = [i if i % 2 == 0 else i*10 for i in range(5)]
条件式がifのみの場合はfor文の後ろに、if-elseの場合はfor文の前に来る。これが少し覚えにくい。
筆者の考え方としては、if-elseは「(配列に何かを格納するのは確定した前提で)何を格納するのかを条件分岐させる」のに対し、ifのみは「配列に格納するかどうかを条件分岐させる」という違いがあることに注目している。上のコードを例にすると
ifのみ
- (条件を満たす):
i
を格納する - (条件を満たさない):何も格納しない
if-else
- (条件を満たす):
i
を格納する - (条件を満たさない):
i*10
を格納する
となっている。
内包の基本表記が
a = [i for i in range(5)]
であり、i
をfor
で回して、そのfor文の前にある内容を配列に格納するという文法であることを考えると、格納が確定しているif-elseはfor文の前に、そうでないifのみ条件式はfor文の後ろに配置するのが妥当である。
つまり、for文の前の条件分岐は「何を格納するか」、後ろの条件式は「格納するかどうか」を判定していると覚えると良い。
内包表記のメリット
等価なコードで示した通り、空の配列を作成した後に要素を追加していく場合に比べ、内包表記は処理速度が速い。
これは、配列に要素が追加される際、何度も配列のメモリ領域を確保するために時間が取られることによる。一方、内包の場合は配列の要素数が確定した後でメモリ領域を一回だけ確保するだけで良い。
内包表記のデメリット
[]
内の記述が難解になる- 複雑な処理を書くことができない(1行で書ける処理に限られる)
内包表記を用いずに、配列生成の速度を上げる方法
配列に格納される要素数が分かっている場合、先に配列のメモリを確保してから値を更新する。
a = [0]*5 # ①
for i in range(5):
a[i] = i
①で0が5つ並んだ(空の)配列を生成している。ここでa = []*5
はa=[]
と等価になってしまうので注意する。
Comments