当サイトは、アフィリエイト広告を利用しています

【Python】リスト内包表記でリストを効率的に生成する方法

作成日:2024月10月09日
更新日:2025年03月20日

pythonでリストを生成する時に
よく使うリスト内包表記について調べたので忘備録として残す

リスト内包表記を使うことで通常のループや関数を使ってリストを作成するよりも、
コードを短く、可読性を高めることができる。

リスト内包表記とは?

リスト内包表記は反復可能オブジェクトから新しリストを作ることができる
リスト作成方法のこと。

たとえば

  • ディクショナリリストから特定の条件にあったディクショナリのみのリストを作成
  • 変換を伴うリスト生成
  • 特定のルールに基づいてリストを生成

など色々なリストを作ることができる。

反復可能オブジェクト(iterable)とは?

反復可能オブジェクトは、要素を順番に取り出すことができるもので
具体的な下記が該当する

  • リスト: [1, 2, 3]
  • タプル: (1, 2, 3)
  • 文字列: "abc"
  • 辞書: {"a": 1, "b": 2}
  • 集合: {1, 2, 3}

リスト内包表記の基本構文

リスト内包表記の基本構文は

リスト内包表記
[for 変数 in iterable if 条件]
  • 式:作成するリストに追加する要素
  • 変数:iterableからの要素を一時的に保持する変数
  • iterable:リスト、タプル、文字列、集合、辞書などの反復可能なオブジェクト
  • 条件:リストへの追加条件を指定。真の場合に追加される

リスト内包表記の実装

実際にディクショナリリストからリスト内包表記を使って
様々な条件のリストを生成してみる。

ディクショナリリスト

ディクショナリリスト
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]

上記からリスト内包表記を使って新しいリストを生成する。

ユーザー名だけのリストを生成する

リスト内包表記_1
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
user_names = [user["name"] for user in users]
print(user_names) # ['Tujimura', 'mori', 'shimada', 'kyogoku']

ユーザー名だけのリストが生成できる

動作確認

リスト内包表記_1

年齢が20歳以上のユーザーのリストを作成する

リスト内包表記_2
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
adult_users = [user for user in users if user["age"] >= 20]
print(adult_users)
# [{'user_id': '2', 'name': 'mori', 'age': 20}, {'user_id': '3', 'name': 'shimada', 'age': 50}, {'user_id': '4', 'name': 'kyogoku', 'age': 70}]

20歳以上のディクショナリだけのリストができる

動作確認

リスト内包表記_2

年齢が50歳以上のユーザーの名前だけをリストにする

リスト内包表記_3
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
older_users_names = [user["name"] for user in users if user["age"] >= 50]
print(older_users_names) # ['shimada', 'kyogoku']

50歳以上のディクショナリの名前だけのリストができる

動作確認

リスト内包表記_3

各ユーザーの名前と年齢の組み合わせのリストを作成する

リスト内包表記_4
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
user_name_age = [(user["name"], user["age"]) for user in users]
print(user_name_age)
# [('Tujimura', 11), ('mori', 20), ('shimada', 50), ('kyogoku', 70)]

名前と年齢だけのタプルができる

動作確認

リスト内包表記_4

ユーザーIDをキー、名前を値とした辞書を作成する

リスト内包表記_5
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
user_dict = {user["user_id"]: user["name"] for user in users}
print(user_dict)
# {'1': 'Tujimura', '2': 'mori', '3': 'shimada', '4': 'kyogoku'}

user_idをキー、名前をバリューにもつディクショナリのリストができる

動作確認

リスト内包表記_5

二つのリストのマッチング処理

マッチング
users_A = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
users_B = [
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
# user_id が一致しているディクショナリだけを取得する
result = [
user_A
for user_A in users_A
if any(
user_A["user_id"] == user_B["user_id"]
for user_B in users_B
)
]
print(result)
# [{'user_id': '3', 'name': 'shimada', 'age': 50}, {'user_id': '4', 'name': 'kyogoku', 'age': 70}]
  • リスト内包表記でusers_Aから1つずつ取り出す
  • 条件式でusers_Aから取り出したディクショナリのuser_idがusers_Bにないかチェック
  • 一致しているディクショナリだけリストにする

※はany()は条件に一致してるものがひとつでもあればtrueを返す

マッチング

まとめ

pythonで色々な条件でリストを生成できるリスト内包表記の使い方について
実装しながらまとめてみた。

実装してみた思ったがかなり汎用性が高い。
高階関数(map等)でも同じことができるがリスト内包表記の方が高速なので
こちらを使った方がよさそう。 ※大量データを処理する場合などは高階関数(map等)を使った方がいい場合もある

高階関数のmapやfilterに関しては下記記事でまとめています。

また処理対象のデータが大量データであったり、またメモリを効率良く使う必要がある
場合は下記で紹介しているジェネレータ式のほうが適している

pythonでリストを生成する時に よく使うリスト内包表記について調べたので忘備録として残す

リスト内包表記を使うことで通常のループや関数を使ってリストを作成するよりも、
コードを短く、可読性を高めることができる。

リスト内包表記とは?

リスト内包表記は反復可能オブジェクトから新しリストを作ることができる
リスト作成方法のこと。

たとえば

  • ディクショナリリストから特定の条件にあったディクショナリのみのリストを作成
  • 変換を伴うリスト生成
  • 特定のルールに基づいてリストを生成

など色々なリストを作ることができる。

反復可能オブジェクト(iterable)とは?

反復可能オブジェクトは、要素を順番に取り出すことができるもので
具体的な下記が該当する

  • リスト: [1, 2, 3]
  • タプル: (1, 2, 3)
  • 文字列: "abc"
  • 辞書: {"a": 1, "b": 2}
  • 集合: {1, 2, 3}

リスト内包表記の基本構文

リスト内包表記の基本構文は

リスト内包表記
[for 変数 in iterable if 条件]
  • 式:作成するリストに追加する要素
  • 変数:iterableからの要素を一時的に保持する変数
  • iterable:リスト、タプル、文字列、集合、辞書などの反復可能なオブジェクト
  • 条件:リストへの追加条件を指定。真の場合に追加される

リスト内包表記の実装

実際にディクショナリリストからリスト内包表記を使って
様々な条件のリストを生成してみる。

ディクショナリリスト

ディクショナリリスト
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]

上記からリスト内包表記を使って新しいリストを生成する。

ユーザー名だけのリストを生成する

リスト内包表記_1
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
user_names = [user["name"] for user in users]
print(user_names) # ['Tujimura', 'mori', 'shimada', 'kyogoku']

ユーザー名だけのリストが生成できる

動作確認

リスト内包表記_1

年齢が20歳以上のユーザーのリストを作成する

リスト内包表記_2
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
adult_users = [user for user in users if user["age"] >= 20]
print(adult_users)
# [{'user_id': '2', 'name': 'mori', 'age': 20}, {'user_id': '3', 'name': 'shimada', 'age': 50}, {'user_id': '4', 'name': 'kyogoku', 'age': 70}]

20歳以上のディクショナリだけのリストができる

動作確認

リスト内包表記_2

年齢が50歳以上のユーザーの名前だけをリストにする

リスト内包表記_3
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
older_users_names = [user["name"] for user in users if user["age"] >= 50]
print(older_users_names) # ['shimada', 'kyogoku']

50歳以上のディクショナリの名前だけのリストができる

動作確認

リスト内包表記_3

各ユーザーの名前と年齢の組み合わせのリストを作成する

リスト内包表記_4
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
user_name_age = [(user["name"], user["age"]) for user in users]
print(user_name_age)
# [('Tujimura', 11), ('mori', 20), ('shimada', 50), ('kyogoku', 70)]

名前と年齢だけのタプルができる

動作確認

リスト内包表記_4

ユーザーIDをキー、名前を値とした辞書を作成する(指定した属性だけの辞書)

リスト内包表記_5
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
user_dict = {user["user_id"]: user["name"] for user in users}
print(user_dict)
# {'1': 'Tujimura', '2': 'mori', '3': 'shimada', '4': 'kyogoku'}

user_idをキー、名前をバリューにもつディクショナリのリストができる

動作確認

リスト内包表記_5

Userインスタンスのリストを作成する

型ヒントを使用してデータのバリデーションを行うライブラリであるpydanticを
使っている場合は、Userインスタンスのリストにすることもできる

リスト内包表記_6
from pydantic import BaseModel
# pydanticデータモデル
class User(BaseModel):
user_id: int
name: str
# ユーザーデータ(辞書のリスト)
users = [
{"user_id": 1, "name": "Tujimura", "age": 11},
{"user_id": 2, "name": "mori", "age": 20},
{"user_id": 3, "name": "shimada", "age": 50},
{"user_id": 4, "name": "kyogoku", "age": 70}
]
# for文内で直接 Userインスタンスを作成
user_instances = [
User(
user_id=user["user_id"],
name=user["name"]
)
for user in users
]
# 結果の確認
print(user_instances)
# [
# User(user_id=1, name='Tujimura'),
# User(user_id=2, name='mori'),
# User(user_id=3, name='shimada'),
# User(user_id=4, name='kyogoku')
# ]
  • ループで必要な属性を取り出す(ageを除外する)
  • ループ内でインスタンスを作る

※fastapiを使ってる場合はpydanticはデフォルトで使える。詳しくは下記記事参照

Userインスタンスのリストを作成する ~model_validate~

BaseModelのmodel_validateを使っても同様のことができる

リスト内包表記_7
from pydantic import BaseModel
# pydanticデータモデル
class User(BaseModel):
user_id: int
name: str
# ユーザーデータ(辞書のリスト)
users = [
{"user_id": 1, "name": "Tujimura", "age": 11},
{"user_id": 2, "name": "mori", "age": 20},
{"user_id": 3, "name": "shimada", "age": 50},
{"user_id": 4, "name": "kyogoku", "age": 70}
]
# model_validateを使う
user_instances = [
User.model_validate(user_data) for user_data in users
]
# 結果の確認
print(user_instances)
# [
# User(user_id=1, name='Tujimura'),
# User(user_id=2, name='mori'),
# User(user_id=3, name='shimada'),
# User(user_id=4, name='kyogoku')
# ]
  • Pydantic v2 では、BaseModelのmodel_validate() はデフォルトで余分なフィールドを無視する
  • dictにageがあっても Userモデルにage が定義されていないため、自動的に削除される
  • Userフィールドに値を追加しても対応できるのでこちらのほうが拡張性が高い

二つのリストのマッチング処理

マッチング
users_A = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
users_B = [
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
# user_id が一致しているディクショナリだけを取得する
result = [
user_A
for user_A in users_A
if any(
user_A["user_id"] == user_B["user_id"]
for user_B in users_B
)
]
print(result)
# [{'user_id': '3', 'name': 'shimada', 'age': 50}, {'user_id': '4', 'name': 'kyogoku', 'age': 70}]
  • リスト内包表記でusers_Aから1つずつ取り出す
  • 条件式でusers_Aから取り出したディクショナリのuser_idがusers_Bにないかチェック
  • 一致しているディクショナリだけリストにする

※はany()は条件に一致してるものがひとつでもあればtrueを返す

マッチング

まとめ

pythonで色々な条件でリストを生成できるリスト内包表記の使い方について
実装しながらまとめてみた。

実装してみた思ったがかなり汎用性が高い。
高階関数(map等)でも同じことができるがリスト内包表記の方が高速なので
こちらを使った方がよさそう。 ※大量データを処理する場合などは高階関数(map等)を使った方がいい場合もある

高階関数のmapやfilterに関しては下記記事でまとめています。

また処理対象のデータが大量データであったり、またメモリを効率良く使う必要がある
場合は下記で紹介しているジェネレータ式のほうが適している

関連記事

新着記事

目次
タグ別一覧
top