[解決!Python]内包表記でリストを作成するには:解決!Python
リスト内包表記を使って、リストを作成する基本と、enumerate関数やzip関数と組み合わせる例、for句をネストしたり内包表記をネストしたりする例を紹介。
# リスト内包表記
squares = [n ** 2 for n in range(5)]
print(squares) # [0, 1, 4, 9, 16]
# 反復可能オブジェクトから渡される値を使用しない例
from random import randint
random_nums = [randint(1, 5) for _ in range(5)]
print(random_nums) # [1, 5, 2, 1, 5]など
# 'a'〜'z'を要素とするリストの作成
chars = [chr(n + ord('a')) for n in range(26)]
print(chars) # ['a', 'b', 'c', 'd', 'e', 'f', 'g', ……, 'v', 'w', 'x', 'y', 'z']
# 'a'〜'z'のASCII値を要素とするリストの作成
s = ''.join(chars)
print(s) # abcdefghijklmnopqrstuvwxyz
ords = [ord(c) for c in s] # 「ords = [ord(c) for c in chars]」でも同様
print(ords) # [97, 98, 99, 100, 101, 102, 103, ……, 118, 119, 120, 121, 122]
# enumerate関数との組み合わせ
words = ['foo', 'bar', 'baz']
indexed_words = [(idx, word) for idx, word in enumerate(words)]
print(indexed_words) # [(0, 'foo'), (1, 'bar'), (2, 'baz')]
# zip関数との組み合わせ
nums1 = [1, 2, 3, 4, 5]
nums2 = [5, 4, 3, 2, 1]
sums = [num1 + num2 for num1, num2 in zip(nums1, nums2)]
print(sums) # [6, 6, 6, 6, 6]
# for句のネスト
nums = [[num1, num2] for num1 in range(3) for num2 in range(2)]
print(nums) # [[0, 0], [0, 1], [1, 0], [1, 1], [2, 0], [2, 1]]
# リスト内包表記のネスト:九九の表を5の段まで
multbl = [[x * y for y in range(1, 10)] for x in range(1, 6)]
for row in multbl:
print(row)
# 出力結果
#[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]
リスト内包表記の基本構文
リスト内包表記の基本構文を以下に示す。
x = [リストの要素を計算する式 for 計算で使用する変数 in 反復可能オブジェクト]
リスト内包表記では、「計算で使用する変数」に「反復可能オブジェクト」の要素が1つずつ渡され、それを使って(あるいは使うことなく)「リストの要素を計算する式」でリスト内包表記により作成されるリストの要素が算出される。同じことをfor文で書くと次のようになる。
x = []
for 計算で使用する変数 in 反復可能オブジェクト:
x.append(リストの要素を計算する式)
このようにfor文では3行(以上)必要な処理がリスト内包表記なら1行で済む。内包表記がどうなるか不安になったら、上に示したようにfor文ではどう書くかを考えてみると、対応する内包表記が見えてくる。
以下では、幾つかの例と、場合によっては同じことをするfor文を示していく。
基本形
例えば、0、1、2、……を二乗した値を要素とするリストを作成することを考える。要素数が少なければ、「squares = [0, 1, 4, 9, 16, ……]」のように手書きでも構わないが、要素数が多いのであれば、これは面倒だし、計算間違いに打ち間違いもあるかもしれない。こうしたことにはコンピューターの力を借りるのが一番だ。
for文を使うと、これは次のようになる。
squares = []
for n in range(5):
squares.append(n ** 2)
print(squares) # [0, 1, 4, 9, 16]
一方、リスト内包表記を使うと、以下のように簡潔にコードを記述できる。
squares = [n ** 2 for n in range(5)]
print(squares) # [0, 1, 4, 9, 16]
この例では、上に示した基本構文の「リストの要素を計算する式」には「n ** 2」が、「計算で使用する変数」には「n」が、「反復可能オブジェクト」には「range(5)」が対応する。
「計算で使用する変数」を使わない場合もある。
from random import randint
random_nums = [randint(1, 5) for _ in range(5)]
print(random_nums) # [1, 5, 2, 1, 5]など
この例は、要素数が5で固定だが、その値はランダムである。こうした場合には、「計算で使用する変数」にはそれを使用しないことを意味する「_」を使うとよい。
内包表記はリストの要素に一定の法則性があるときには、その法則を反映するような式を記述することで、リストなどの作成が容易になる。以下の例はアルファベットを要素とするリストを作成するものだ。
chars = [chr(n + ord('a')) for n in range(26)]
print(chars) # ['a', 'b', 'c', 'd', 'e', 'f', 'g', ……, 'v', 'w', 'x', 'y', 'z']
アルファベット(小文字)は26文字で構成され、Pythonでは'a'から'z'まで順番にコードが割り振られている。上の例はこのことを利用して、リスト内包表記によりリストを作成するものだ。「chr(n + ord('a'))」という式は、ord('a')により'a'に割り振られているコードを取得して、その値にrange関数で得られる0、1、2、……、25という値を足した結果をchr関数に渡すことで、アルファベットを1文字ずつ得ることを意味している。
「反復可能オブジェクト」にはrange関数の戻り値であるrangeオブジェクト以外のオブジェクトも指定できる。例えば、リストや文字列がそうだ。以下は上で作成したアルファベットを要素とするリストから文字列を作成して、反復可能オブジェクトとしてリスト内包表記に渡す例である。
s = ''.join(chars)
print(s) # abcdefghijklmnopqrstuvwxyz
ords = [ord(c) for c in s] # 「ords = [ord(c) for c in chars]」でも同様
print(ords) # [97, 98, 99, 100, 101, 102, 103, ……, 118, 119, 120, 121, 122]
この例では、「計算で使用する変数」にアルファベットの各文字が順次渡されるので、ord関数を使ってそれぞれの文字に割り振られたコードを含むリストを作成している。また、上で述べた法則「'a'から'z'まで順番にコードが割り振られている」ことも確認できるはずだ。
enumerate関数との組み合わせ
内包表記に渡す反復可能オブジェクトとそのインデックスを使用したいときにはenumerate関数と組み合わせる。以下に例を示す。
words = ['foo', 'bar', 'baz']
indexed_words = [(idx, word) for idx, word in enumerate(words)]
print(indexed_words) # [(0, 'foo'), (1, 'bar'), (2, 'baz')]
この例では、enumerate関数と文字列リストを組み合わせて、「(インデックス, その値)」というタプルを要素とするリストを作成している。
zip関数との組み合わせ
複数のリストの(同じインデックス位置にある)要素から新たにリストを作成するには、zip関数と組み合わせる。以下に例を示す。
nums1 = [1, 2, 3, 4, 5]
nums2 = [5, 4, 3, 2, 1]
sums = [num1 + num2 for num1, num2 in zip(nums1, nums2)]
print(sums) # [6, 6, 6, 6, 6]
この例では、2つのリストnum1とnum2をzip関数でまとめて、それらの同じインデックス位置にある値の和を要素とするリストを作成している。
for句のネスト
Copyright© Digital Advantage Corp. All Rights Reserved.