[解決!Python]map関数でリストに関数やラムダ式(無名関数)を適用するには:解決!Python
Pythonに組み込みのmap関数を使って、反復可能オブジェクトの要素に対して、一括で何らかの処理を適用する方法を紹介する。
result = map(int, ['1', '2', '3']) # リスト(反復可能オブジェクト)の要素を整数化
# map関数の戻り値はイテレータ(mapオブジェクト)
print(result) # <map object at 0xXYZ...>
for item in result: # forループで処理する
print(item, type(item))
# 出力結果:
#1 <class 'int'>
#2 <class 'int'>
#3 <class 'int'>
# list関数でリストに変換する
result = map(int, ['1', '2', '3']) # list関数でイテレータをリストに変換
result = list(result)
print(result) # [1, 2, 3]
# 同じことをするリスト内包表記
result = [int(num) for num in ['1', '2', '3']]
# 第2引数には反復可能オブジェクトを指定する
result = map(int, '123') # 文字列は反復可能オブジェクト
# result = [int(num) for num in '123']
result = list(result) # イテレータをリストに変換
print(result) # [1, 2, 3]
# 辞書の要素
d = {'foo': '_foo_', 'bar': '_bar_', 'baz': '_baz_'}
result = map(str.upper, d) # キーを反復
# result = [item.upper() for item in d]
print(list(result)) # ['FOO', 'BAR', 'BAZ']
result = map(str.upper, d.values()) # 値を反復
# result = [item.upper() for item in d.values()]
print(list(result)) # ['_FOO_', '_BAR_', '_BAZ_']
result = map(lambda item: f'{item[0]} : {item[1]}', d.items()) # キー/値を反復
# result = [f'{item[0]} : {item[1]}' for item in d.items()]
print(list(result)) # ['foo : _foo_', 'bar : _bar_', 'baz : _baz_']
# 第1引数には呼び出し可能なオブジェクトを指定する
# ユーザー定義関数
def subtract_1(num):
return num - 1
result = map(subtract_1, [0, 1, 2])
# result = [subtract_1(item) for item in [0, 1, 2]]
print(list(result)) # [-1, 0, 1]
# ラムダ式
result = map(lambda x: x - 1, [0, 1, 2])
# result = [item - 1 for item in [0, 1, 2]]
print(list(result)) # [-1, 0, 1]
# 呼び出し可能なインスタンス
class Subtract:
def __init__(self, subtracter=1):
self.subtracter = subtracter
def __call__(self, num):
return num - self.subtracter
subtract_1_from = Subtract(1)
print(subtract_1_from(10)) # 9
result = map(subtract_1_from, [0, 1, 2])
# result = [subtract_1_from(item) for item in [0, 1, 2]]
print(list(result)) # [-1, 0, 1]
# 反復可能オブジェクトを複数指定
l1 = ['foo', 'bar', 'baz']
l2 = [0, 1, 2, 3]
result = map(lambda x, y: f'{x} and {y}', l1, l2)
# result = [f'{x} and {y}' for x, y in zip(l1, l2)]
print(list(result)) # ['foo and 0', 'bar and 1', 'baz and 2']
result = map(lambda x, y, z: f'{x} and {y} and {z}', l1, l2)
print(list(result)) # TypeError
map関数の基本
Pythonのmap関数は、反復可能オブジェクト(iterable、イテラブル)に格納されている一連の要素に対して、何らかの処理を適用し、適用後の要素を反復するイテレータを返送する。
map(function, iterable, ……)
反復可能オブジェクトに適用する処理を第1引数に、処理を適用する反復可能オブジェクトを第2引数に指定する。第3引数以降にさらに反復可能オブジェクトを指定することも可能だ(後述)。
処理と反復可能オブジェクトを1つずつ指定するのが、map関数の基本的な使い方となる。以下に例を示す。
result = map(int, ['1', '2', '3']) # リストの要素を整数化
# map関数の戻り値はイテレータ(mapオブジェクト)
print(result) # <map object at 0xXYZ...>
ここでは反復可能オブジェクトとして数字を要素とするリストを、それに適用する処理としてint関数を指定している。これにより、整数化された要素を反復するイテレータが返される。そのため、戻り値をそのまま画面に出力しようとしても、上の最終行のように要素ではなく、戻り値であるイテレータ(mapオブジェクト)が出力されるだけである点には注意しよう。
イテレータの中身はforループで取り出したり、list関数でリストに変換したりできる。以下はforループでその要素と型を表示したところだ。int関数により、数字がint型のオブジェクトになったことが分かる。
for item in result: # forループで処理する
print(item, type(item))
# 出力結果:
#1 <class 'int'>
#2 <class 'int'>
#3 <class 'int'>
list関数でイテレータをリストに変換するには次のようにする(上のコードを実行した直後にlist(result)を実行しても、イテレータは既に要素を反復しつくしているので、生成されるのは空のリストとなる点に注意)。
result = map(int, ['1', '2', '3']) # list関数でイテレータをリストに変換
result = list(result)
print(result) # [1, 2, 3]
なお、Pythonでは一般にmap関数よりもリスト内包表記やジェネレーター式を使用することが推奨される。上と同じことをするリスト内包表記を以下に示す。
result = [int(num) for num in ['1', '2', '3']]
リスト内包表記はもちろんリストを生成し、map関数はイテレータを返す。大量のデータに一括で処理を適用し、その後、処理済みの要素を逐次的に処理したいといった場合にメモリ量が問題になるのであれば、map関数は選択肢として考えてもよいだろう。なお、以降ではリスト内包表記で同じことをするとどんなコードになるかをコメントアウトして示すことにする。
反復可能オブジェクト
Copyright© Digital Advantage Corp. All Rights Reserved.