コンテンツにスキップ

Python/コレクション

出典: フリー教科書『ウィキブックス(Wikibooks)』

イントロダクション

[編集]

コレクションとは何か?

[編集]

コレクションとは、複数のデータを一つの単位として扱うためのデータ構造です。Pythonでは、リスト、タプル、辞書、集合といった基本的なコレクションが提供されています。これらを使うことで、データを効率的に管理、操作することができます。

Pythonにおけるコレクションの重要性

[編集]

コレクションはPythonプログラミングの基礎であり、ほとんどのプログラムで使用されます。データの集まりを簡単に操作できるため、コレクションを理解することは、Pythonの効果的なプログラミングに不可欠です。

基本的なコレクションの種類

[編集]

Pythonでよく使われるコレクションには以下のものがあります:

リスト (List)

[編集]

リストの基本操作

[編集]

リストは可変長で順序付けられたコレクションです。リストの基本操作には、作成、アクセス、更新、削除があります。

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

# 要素へのアクセス
print(fruits[0])  # apple

# 要素の更新
fruits[1] = "blueberry"
print(fruits)  # ["apple", "blueberry", "cherry"]

# 要素の削除
del fruits[2]
print(fruits)  # ["apple", "blueberry"]

リストのメソッド

[編集]

リストは多くの便利なメソッドを提供しています。

# リストの作成
numbers = [1, 2, 3, 4]

# 要素の追加
numbers.append(5)
print(numbers)  # [1, 2, 3, 4, 5]

# リストの結合
numbers.extend([6, 7])
print(numbers)  # [1, 2, 3, 4, 5, 6, 7]

# 指定位置に要素を挿入
numbers.insert(3, 3.5)
print(numbers)  # [1, 2, 3, 3.5, 4, 5, 6, 7]

# 要素の削除
numbers.remove(3.5)
print(numbers)  # [1, 2, 3, 4, 5, 6, 7]

# 最後の要素の削除と返却
last = numbers.pop()
print(last)  # 7
print(numbers)  # [1, 2, 3, 4, 5, 6]

# リストのクリア
numbers.clear()
print(numbers)  # []

# リストのコピー
numbers = [1, 2, 3]
numbers_copy = numbers.copy()
print(numbers_copy)  # [1, 2, 3]

リストのスライシングとリスト内包表記

[編集]

スライシング

[編集]

リストの一部を取り出すにはスライシングを使います。

# リストの作成
fruits = ["apple", "banana", "cherry", "date", "elderberry"]

# スライスを使って要素を取り出す
print(fruits[1:3])  # ["banana", "cherry"]
print(fruits[:2])  # ["apple", "banana"]
print(fruits[3:])  # ["date", "elderberry"]
print(fruits[-3:])  # ["cherry", "date", "elderberry"]

リスト内包表記

[編集]

リスト内包表記を使うと、リストの生成や変換が簡単に行えます。

# リスト内包表記の例
squares = [x ** 2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

リストの実践例

[編集]

単語リストの管理

[編集]
# 単語リストの作成
words = ["apple", "banana", "cherry"]

# 単語の追加
words.append("date")
print(words)  # ["apple", "banana", "cherry", "date"]

# 単語の削除
words.remove("banana")
print(words)  # ["apple", "cherry", "date"]

数値リストの処理

[編集]
# 数値リストの作成
numbers = [1, 2, 3, 4, 5]

# 平均値の計算
average = sum(numbers) / len(numbers)
print(average)  # 3.0

タプル (Tuple)

[編集]

タプルの基本操作

[編集]

タプルは不変(immutable)で順序付けられたコレクションです。一度作成すると、要素を変更できません。

# タプルの作成
coordinates = (10.0, 20.0)

# 要素へのアクセス
print(coordinates[0])  # 10.0

# タプルのアンパック
x, y = coordinates
print(x, y)  # 10.0 20.0

# 要素の削除(タプルは不変なのでエラーが発生)
# del coordinates[0]  # TypeError

タプルの用途と利点

[編集]

タプルは不変であるため、データの整合性が必要な場合に使用されます。例えば、辞書のキーや関数の戻り値として使うと良いでしょう。

タプルの実践例

[編集]

座標の表現

[編集]
# 座標をタプルで表現
point = (5.0, 10.0)

# 要素へのアクセス
print(f"x: {point[0]}, y: {point[1]}")  # x: 5.0, y: 10.0

関数からの複数戻り値

[編集]
def min_max(numbers):
    return min(numbers), max(numbers)

# 関数の呼び出し
result = min_max([1, 2, 3, 4, 5])
print(result)  # (1, 5)

辞書 (Dictionary)

[編集]

辞書の基本操作

[編集]

辞書はキーと値のペアを保持するコレクションです。

# 辞書の作成
person = {"name": "Alice", "age": 25}

# 要素へのアクセス
print(person["name"])  # Alice

# 要素の更新
person["age"] = 26
print(person)  # {"name": "Alice", "age": 26}

# 要素の追加
person["city"] = "New York"
print(person)  # {"name": "Alice", "age": 26, "city": "New York"}

# 要素の削除
del person["age"]
print(person)  # {"name": "Alice", "city": "New York"}

辞書のメソッド

[編集]

辞書も多くの便利なメソッドを提供しています。

# 辞書の作成
car = {"brand": "Ford", "model": "Mustang", "year": 1964}

# キーの取得
keys = car.keys()
print(keys)  # dict_keys(['brand', 'model', 'year'])

# 値の取得
values = car.values()
print(values)  # dict_values(['Ford', 'Mustang', 1964])

# キーと値のペアの取得
items = car.items()
print(items)  # dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 1964)])

# getメソッド
model = car.get("model")
print(model)  # Mustang

# updateメソッド
car.update({"color": "red"})
print(car)  # {"brand": "Ford", "model": "Mustang", "year": 1964, "color": "red"}

# popメソッド
year = car.pop("year")
print(year)  # 1964
print(car)  # {"brand": "Ford", "model": "Mustang", "color": "red"}

# popitemメソッド
item = car.popitem()
print(item)  # ('color', 'red')
print(car)  # {"brand": "Ford", "model": "Mustang"}

# clearメソッド
car.clear()
print(car)  # {}

ネストされた辞書

[編集]

辞書の中に辞書を入れることで、複雑なデータ構造を表現できます。

# ネストされた辞書の作成
employee = {
    "name": "John",
    "age": 30,
    "job": {
        "title": "Developer",
        "department": "IT"
    }
}

# ネストされた要素へのアクセス
print(employee["job"]["title"])  # Developer

辞書の実践例

[編集]

電話帳

[編集]
# 電話帳の作成
phone_book = {
    "Alice": "123-456-7890",
    "Bob": "987-654-3210"
}

# 電話番号の取得
print(phone_book["Alice"])  # 123-456-7890

# 電話番号の追加
phone_book["Charlie"] = "555-555-5555"
print(phone_book)  # {"Alice": "123-456-7890", "Bob": "987-654-3210", "Charlie": "555-555-5555"}

設定オプションの管理

[編集]
# 設定オプションの作成
settings = {
    "theme": "dark",
    "language": "English",
    "notifications": True
}

# 設定の変更
settings["theme"] = "light"
print(settings)  # {"theme": "light", "language": "English", "notifications": True}

集合 (Set)

[編集]

集合の基本操作

[編集]

集合は重複しない要素のコレクションで、順序は保証されません。

# 集合の作成
fruits = {"apple", "banana", "cherry"}

# 要素の追加
fruits.add("date")
print(fruits)  # {"apple", "banana", "cherry", "date"}

# 要素の削除
fruits.remove("banana")
print(fruits)  # {"apple", "cherry", "date"}

# 要素の存在確認
print("apple" in fruits)  # True
print("banana" in fruits)  # False

集合のメソッド

[編集]

集合は他にも多くのメソッドを提供しています。

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

# 集合の結合
numbers.update({6, 7})
print(numbers)  # {1, 2, 3, 4, 5, 6, 7}

# 要素の削除
numbers.discard(7)
print(numbers)  # {1, 2, 3, 4, 5, 6}

# 要素の削除と返却
last = numbers.pop()
print(last)  # 1 (要素は順不同で返されるため、実行ごとに異なる可能性あり)
print(numbers)  # {2, 3, 4, 5, 6}

# 集合のクリア
numbers.clear()
print(numbers)  # {}

集合演算

[編集]

集合は数学的な集合演算をサポートしています。

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

# 和集合
union = set1.union(set2)
print(union)  # {1, 2, 3, 4, 5}

# 積集合
intersection = set1.intersection(set2)
print(intersection)  # {3}

# 差集合
difference = set1.difference(set2)
print(difference)  # {1, 2}

# 対称差集合
sym_diff = set1.symmetric_difference(set2)
print(sym_diff)  # {1, 2, 4, 5}

集合の実践例

[編集]

重複の排除

[編集]
# リストから重複を排除
numbers = [1, 2, 2, 3, 4, 4, 5]
unique_numbers = set(numbers)
print(unique_numbers)  # {1, 2, 3, 4, 5}

要素の一意性チェック

[編集]
# 一意の要素を持つかどうかのチェック
def has_unique_elements(lst):
    return len(lst) == len(set(lst))

print(has_unique_elements([1, 2, 3, 4]))  # True
print(has_unique_elements([1, 2, 2, 3]))  # False

データ構造の比較

[編集]

リスト vs タプル

[編集]

リストは可変であり、要素の追加、削除が可能ですが、タプルは不変であり、要素を変更することはできません。タプルは、変更されることを防ぐためのデータの固定に適しています。

リスト vs 辞書

[編集]

リストは順序付けられた要素の集まりであり、インデックスでアクセスします。辞書はキーと値のペアであり、キーでアクセスします。検索操作が多い場合、辞書が適しています。

辞書 vs 集合

[編集]

辞書はキーと値のペアを持ち、集合は一意の要素の集まりです。辞書はキーでの高速アクセスが必要な場合に使用し、集合は重複を排除する必要がある場合に使用します。

データ構造の選択基準

[編集]
  • データの変更が必要かどうか
  • データの検索方法(インデックスかキーか)
  • 重複を許すかどうか
  • パフォーマンス要件(検索速度、メモリ使用量)

コレクションの応用

[編集]

コレクションを使った問題解決の例

[編集]

高度なリスト内包表記

[編集]
# 二次元リストを一次元リストにフラット化
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat_list = [num for row in matrix for num in row]
print(flat_list)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

辞書内包表記

[編集]
# キーと値を逆にした辞書の作成
original = {"a": 1, "b": 2, "c": 3}
inverse = {value: key for key, value in original.items()}
print(inverse)  # {1: "a", 2: "b", 3: "c"}

セット内包表記

[編集]
# 文字列中の一意の文字を小文字に変換
input_str = "Hello World"
unique_chars = {char.lower() for char in input_str if char.isalpha()}
print(unique_chars)  # {'h', 'e', 'l', 'o', 'w', 'r', 'd'}

コレクションモジュール

[編集]

`collections`モジュールの紹介

[編集]

Pythonの`collections`モジュールは、標準のデータ構造に加え、さらに便利なデータ構造を提供します。

deque

[編集]

デック(deque)は両端での追加と削除が高速なリストです。

from collections import deque

# デックの作成
d = deque([1, 2, 3])
d.append(4)
d.appendleft(0)
print(d)  # deque([0, 1, 2, 3, 4])

d.pop()
d.popleft()
print(d)  # deque([1, 2, 3])

namedtuple

[編集]

名前付きタプルは、タプルに名前を付けてアクセスしやすくしたものです。

from collections import namedtuple

# namedtupleの定義
Point = namedtuple("Point", ["x", "y"])

# namedtupleの作成
p = Point(10, 20)
print(p.x, p.y)  # 10 20

defaultdict

[編集]

デフォルト値を持つ辞書です。

from collections import defaultdict

# defaultdictの作成
dd = defaultdict(int)
dd["count"] += 1
print(dd)  # defaultdict(<class 'int'>, {'count': 1})

Counter

[編集]

要素の出現回数をカウントするための辞書です。

from collections import Counter

# Counterの使用例
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
counter = Counter(words)
print(counter)  # Counter({'apple': 3, 'banana': 2, 'orange': 1})

OrderedDict

[編集]

順序を保持する辞書です。

from collections import OrderedDict

# OrderedDictの作成


od = OrderedDict()
od["first"] = 1
od["second"] = 2
print(od)  # OrderedDict([('first', 1), ('second', 2)])

ChainMap

[編集]

複数の辞書をまとめて一つの辞書のように扱います。

from collections import ChainMap

# 複数の辞書の作成
dict1 = {"one": 1, "two": 2}
dict2 = {"three": 3, "four": 4}

# ChainMapの作成
chain = ChainMap(dict1, dict2)
print(chain)  # ChainMap({'one': 1, 'two': 2}, {'three': 3, 'four': 4})
print(chain["three"])  # 3

各コレクションの用途と使い方

[編集]

各コレクションは特定の用途に最適化されています。例えば、dequeは両端での追加と削除が高速なため、キューやスタックの実装に適しています。Counterは要素の出現回数を簡単にカウントできるため、頻度分析に便利です。

`collections`モジュールの実践例

[編集]

順序付き辞書

[編集]
# 順序付き辞書を使ってソート
from collections import OrderedDict

# 通常の辞書
d = {"banana": 3, "apple": 4, "pear": 1, "orange": 2}

# ソートした順序付き辞書の作成
sorted_d = OrderedDict(sorted(d.items(), key=lambda t: t[1]))
print(sorted_d)  # OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

カウンターの使用

[編集]
# 単語の頻度をカウント
from collections import Counter

# 文章の単語をカウント
text = "hello world hello"
words = text.split()
counter = Counter(words)
print(counter)  # Counter({'hello': 2, 'world': 1})

章末問題と練習

[編集]

各コレクションに関する練習問題

[編集]

1. リストの要素を逆順にする関数を実装してください。 2. タプルから特定の要素を削除する関数を実装してください。(ヒント:新しいタプルを作成する) 3. 辞書のキーと値を逆にした新しい辞書を作成してください。 4. 集合の共通要素を見つける関数を実装してください。

応用問題

[編集]

1. `collections`モジュールの`deque`を使って、効率的なFIFOキューを実装してください。 2. `namedtuple`を使って、学生の情報(名前、年齢、成績)を管理するクラスを実装してください。 3. `defaultdict`を使って、リストの要素の頻度をカウントする関数を実装してください。 4. `OrderedDict`を使って、辞書のキーを値の昇順でソートする関数を実装してください。

解答例と解説

[編集]

以下は練習問題の解答例です。

1. リストの要素を逆順にする関数

def reverse_list(lst):
    return lst[::-1]

print(reverse_list([1, 2, 3, 4, 5]))  # [5, 4, 3, 2, 1]

2. タプルから特定の要素を削除する関数

def remove_from_tuple(tpl, element):
    return tuple(x for x in tpl if x != element)

print(remove_from_tuple((1, 2, 3, 4, 3), 3))  # (1, 2, 4)

3. 辞書のキーと値を逆にした新しい辞書を作成

def invert_dict(d):
    return {v: k for k, v in d.items()}

print(invert_dict({"a": 1, "b": 2, "c": 3}))  # {1: "a", 2: "b", 3: "c"}

4. 集合の共通要素を見つける関数

def common_elements(set1, set2):
    return set1 & set2

print(common_elements({1, 2, 3}, {2, 3, 4}))  # {2, 3}