<一覧に戻る

適切なデータ構造の選択

「リストと辞書、どっちを使えばいいんだろう?」そんな迷いは、Pythonを学び始めた多くの人が通る道です。

実は、データ構造の選び方が、コードの読みやすさや実行速度を大きく左右します。Pythonにはリスト、タプル、辞書、集合といった便利な入れ物がそろっていて、状況に合わせて選ぶだけで、ムダの少ない気持ちのいいコードになります。

まずは、それぞれの性質と基本の使い方をイメージしやすい例で確認し、そのあとで「どう選ぶか」の目安をまとめていきましょう。自分のケースに当てはめながら読むと、グッと理解が深まります。

では、最も出番の多いリストから見ていきましょう。

リスト(List)

リストは順番がある、あとから中身を変えられる入れ物です。

買い物リストのように、順番を保ちながら項目を追加・削除・差し替えしたいときにピッタリです。整数や文字列など種類の違うデータを混ぜて入れても問題ありません。

# リストの作成
fruits = ['apple', 'banana', 'cherry']

# 要素の追加
fruits.append('orange')

# 要素の削除
fruits.remove('banana')

# 要素の変更
fruits[0] = 'grape'

# リストの表示
print(fruits)

このコードでは、最初に3つの文字列からなるリストを作り、あとからオレンジを追加しています。不要になったバナナはremoveで取り除き、先頭の要素はインデックス0を指定してぶどうに差し替えました。printで中身を表示すると、操作の結果がそのまま順番つきで確認できます。順番も大事だし、後から編集もしたいというときは、まずリストを思い出してください。

次に、似ているようで大きく性質が違うタプルを見てみましょう。

タプル(Tuple)

タプルは順番はあるけれど、作ったあとに中身を変えない入れ物です。

地図の座標(x, y)や、年月日(year, month, day)のように、ひとかたまりで意味があり、変更の必要がない値に向いています。変更できないぶん、リストより軽くて扱いが速いこともあります

# タプルの作成
coordinates = (10, 20)

# タプルの要素へのアクセス
x, y = coordinates

# タプルの表示
print(f"X: {x}, Y: {y}")

ここでは座標をタプルで表し、xとyに分解して取り出しています。タプルは「決まった2つ(または複数)の値がセットで動く」ときに読みやすく、安全です。変更できない性質のおかげで、辞書のキーとして使えるなど、後で役立つ場面も出てきます。

次は、名前で値を取り出せる、便利な「引き出し」タイプの辞書です。

辞書(Dictionary)

辞書はキー(ラベル)と値をペアで持つ入れ物です。

英単語と意味の対応表のように、名前で素早く探したいというときに大活躍します。キーは重複できませんが、値は同じでもかまいません。

# 辞書の作成
person = {
    'name': 'Alice',
    'age': 30,
    'city': 'New York'
}

# 値の取得
name = person['name']

# 値の追加
person['email'] = 'alice@example.com'

# 値の変更
person['age'] = 31

# 辞書の表示
print(person)

この例では、人の情報を「name」「age」「city」といったキーで管理しています。名前の取得はperson['name']のように、ラベルを指定するだけ。あとからemailを足したり、年齢を更新したりするのも簡単です。「項目名で直接アクセスしたい」「検索を速くしたい」と感じたら、辞書を第一候補にしましょう。

最後は、重複を自動でなくしてくれる集合を見てみます。

集合(Set)

集合は順番がなく、同じ値を重ねて持たない入れ物です。

リストの中から重複を取り除きたいときや、共通点・違いを調べるような“集合演算”に向いています。ある値が含まれているかどうかのチェックも得意です。

# 集合の作成
numbers = {1, 2, 3, 4, 5}

# 要素の追加
numbers.add(6)

# 要素の削除
numbers.remove(3)

# 集合の表示
print(numbers)

# 他の集合との和集合
other_numbers = {4, 5, 6, 7, 8}
union = numbers.union(other_numbers)

# 和集合の表示
print(union)

このコードでは、重複のない数値の集まりを作り、要素を足したり削ったりしています。さらに、ほかの集合との和集合を求めることで、両方の要素をまとめた結果が得られます。順番に意味がないデータや、重複排除・素早い含有判定が必要なデータに適しています。

ここまでで4つの基本がそろいました。「結局、どれを選べばいいの?」という疑問に、次で答えていきます。

適切なデータ構造の選択のための基準

選び方に迷ったときは、次の観点を順番にチェックすると判断しやすくなります。

  • 【可変性は必要か?】 後から追加・削除・更新があるならリストや辞書。固定で良いならタプルが安全で軽量です。
  • 【順序は重要か?】 並び順を保ちたいならリストやタプル。順序に意味がないなら集合でシンプルにできます。
  • 【どうやって探すか?】 位置(インデックス)で扱うならリスト、名前(キー)で即座に取り出したいなら辞書、含まれているかのチェックを速くしたいなら集合が向いています。
  • 【値は重複しても良いか?】 重複を自動で避けたいなら集合、重複を許したいならリスト。
  • 【変更の安全性は大事か?】 間違えて書き換えたくないデータはタプルにすると意図が伝わり、バグも予防できます。

「先頭に頻繁に追加・削除したい」など特別な操作が多い場合は、標準ライブラリのcollections.dequeのような専用構造が役立つこともあります。まずは基本4種で十分ですが、「操作の回数が多くて遅い」と感じたら、より適した入れ物がないかを探してみましょう。

小さな実践例でイメージを固める

言葉だけだとピンと来ないこともありますよね。よくある作業を、最適な入れ物でサッと体験してみましょう。

重複の除去と高速な含有チェック(集合)

emails = ['a@example.com', 'b@example.com', 'a@example.com']
unique = set(emails)

print('a@example.com' in unique)  # True(高速)
print(unique)                     # {'a@example.com', 'b@example.com'}

リストのままでは同じアドレスが重なりますが、集合にすると一発で重複が消えます。さらに、含まれているかどうかのチェックも集合が得意です。

キーで素早く検索(辞書)

users = {
    101: 'Alice',
    102: 'Bob',
    103: 'Carol',
}

print(users[102])  # 'Bob'

番号(キー)から名前(値)をすぐに取り出せます。リストを順に探すよりも直感的で高速です。

まとめ

今回学習した内容をまとめます。

  • とりあえず順序つきで増減可能ならリスト。
  • 名前で引ける形にしたいなら辞書。
  • 変えたくないひとかたまりならタプル。
  • 重複をなくしたい、含有チェックを速くしたいなら集合。

データ構造の選択は「正解がひとつ」ではなく、「目的に合っているか」が大切です。今の用途に合う入れ物を選べば、コードは読みやすく、パフォーマンスも自然と良くなります。あなたのプログラムで一番大事なのは何でしょう? 順序、検索の速さ、重複の扱い、変更のしやすさ。優先順位をはっきりさせれば、選ぶべきデータ構造が見えてきます。

出力結果: