Python データ型とアルゴリズム

データ型とアルゴリズムに関するトピックについて、まずは sorted と sort から解説を始めます。

セクション1: sorted と sort

sorted 関数

sorted 関数は、任意のイテラブル(リスト、タプル、文字列など)をソートし、新しいソート済みのリストを返します。元のリストは変更されません。

基本的な使い方

numbers = [5, 2, 9, 1, 5, 6]
sorted_numbers = sorted(numbers)
print(sorted_numbers)  # [1, 2, 5, 5, 6, 9]
print(numbers)  # [5, 2, 9, 1, 5, 6]

引数 reverse を使用

ソート順を逆にするには、reverse=True を指定します。

sorted_numbers = sorted(numbers, reverse=True)
print(sorted_numbers)  # [9, 6, 5, 5, 2, 1]

引数 key を使用

key 引数を使ってカスタムソートができます。例えば、文字列の長さでソートする場合です。

words = ["banana", "apple", "cherry", "date"]
sorted_words = sorted(words, key=len)
print(sorted_words)  # ['date', 'apple', 'banana', 'cherry']

sort メソッド

sort メソッドはリスト専用であり、リスト自体をソートします。元のリストが変更されます。

基本的な使い方

numbers = [5, 2, 9, 1, 5, 6]
numbers.sort()
print(numbers)  # [1, 2, 5, 5, 6, 9]

引数 reverse を使用

ソート順を逆にするには、reverse=True を指定します。

numbers.sort(reverse=True)
print(numbers)  # [9, 6, 5, 5, 2, 1]

引数 key を使用

key 引数を使ってカスタムソートができます。例えば、文字列の長さでソートする場合です。

words = ["banana", "apple", "cherry", "date"]
words.sort(key=len)
print(words)  # ['date', 'apple', 'banana', 'cherry']

operator モジュール

operator モジュールは、一般的な演算子を関数として提供します。これにより、ソートやフィルタリングの際に便利です。

基本的な演算子関数

operator.add(a, b):a + b を計算します。
operator.sub(a, b):a - b を計算します。
operator.mul(a, b):a * b を計算します。
operator.truediv(a, b):a / b を計算します。

import operator

a, b = 5, 3
print(operator.add(a, b))  # 8
print(operator.sub(a, b))  # 2
print(operator.mul(a, b))  # 15
print(operator.truediv(a, b))  # 1.666...

ソートでの使用例

operator.itemgetter を使って、ネストされたリストや辞書をソートできます。

import operator

students = [
    {'name': 'John', 'age': 25},
    {'name': 'Jane', 'age': 22},
    {'name': 'Dave', 'age': 27}
]

# 年齢でソート
sorted_students = sorted(students, key=operator.itemgetter('age'))
print(sorted_students)
# [{'name': 'Jane', 'age': 22}, {'name': 'John', 'age': 25}, {'name': 'Dave', 'age': 27}]

collections モジュール

collections モジュールは、Pythonの組み込みコレクションデータ型に対する便利な拡張を提供します。

1. namedtuple

namedtuple は、タプルのサブクラスで、フィールドに名前を付けることができます。

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])
p = Point(11, y=22)
print(p.x, p.y)  # 11 22

2. deque

deque は、両端キューであり、O(1) で両端に要素を追加・削除できます。

from collections import deque

d = deque(['a', 'b', 'c'])
d.append('d')
print(d)  # deque(['a', 'b', 'c', 'd'])
d.appendleft('z')
print(d)  # deque(['z', 'a', 'b', 'c', 'd'])
d.pop()
print(d)  # deque(['z', 'a', 'b', 'c'])
d.popleft()
print(d)  # deque(['a', 'b', 'c'])

3. Counter

Counter は、要素のカウントを行うディクショナリサブクラスです。

from collections import Counter

c = Counter('gallahad')
print(c)  # Counter({'a': 3, 'l': 2, 'g': 1, 'h': 1, 'd': 1})

# 最も一般的な要素を取得
print(c.most_common(2))  # [('a', 3), ('l', 2)]

4. defaultdict

defaultdict は、キーが存在しない場合にデフォルト値を返すディクショナリです。

from collections import defaultdict

d = defaultdict(int)
d['key1'] += 1
print(d)  # defaultdict(<class 'int'>, {'key1': 1})

d = defaultdict(list)
d['key2'].append('value')
print(d)  # defaultdict(<class 'list'>, {'key2': ['value']})

セクション4: enum モジュール

enum モジュールは、列挙型を定義するために使用されます。列挙型は一連のシンボリック名を持つ定数を作成します。

基本的な使用方法

from enum import Enum, auto

class Color(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

print(Color.RED)  # Color.RED
print(Color.RED.name)  # RED
print(Color.RED.value)  # 1

メンバーの比較

if Color.RED == Color.RED:
    print("Equal")  # Equal
if Color.RED != Color.GREEN:
    print("Not Equal")  # Not Equal

まとめ

ここまでで、sorted と sort、operator モジュール、collections モジュール、enum モジュールについて解説しました

セクション5: itertools モジュール

itertools モジュールは、イテラブルの操作を効率化するためのツールを提供します。これらのツールは、イテレータを生成するための関数の集まりです。

1. count

無限にカウントアップするイテレータを生成します。

import itertools

for i in itertools.count(10, 2):
    if i > 20:
        break
    print(i)
# 10, 12, 14, 16, 18, 20

2. cycle

与えられたイテラブルを無限にサイクルします。

import itertools

counter = 0
for item in itertools.cycle(['A', 'B', 'C']):
    if counter > 6:
        break
    print(item)
    counter += 1
# A, B, C, A, B, C, A

3. repeat

指定された値を繰り返し返すイテレータを生成します。

import itertools

for item in itertools.repeat('Hello', 3):
    print(item)
# Hello, Hello, Hello

4. chain

複数のイテラブルを1つに連結します。

import itertools

list1 = [1, 2, 3]
list2 = [4, 5, 6]
for item in itertools.chain(list1, list2):
    print(item)
# 1, 2, 3, 4, 5, 6

5. compress

対応する真偽値リストに基づいて、イテラブルから要素を選択します。

import itertools

data = ['A', 'B', 'C', 'D']
selectors = [True, False, True, False]
for item in itertools.compress(data, selectors):
    print(item)
# A, C

6. dropwhile と takewhile

条件が満たされる間イテレータの要素をスキップし、条件が満たされている間要素を取得します。

import itertools

data = [1, 2, 3, 4, 5, 6]
for item in itertools.dropwhile(lambda x: x < 3, data):
    print(item)
# 3, 4, 5, 6

for item in itertools.takewhile(lambda x: x < 4, data):
    print(item)
# 1, 2, 3

7. product

直積を計算します。ネストされたループを使って生成できるすべての組み合わせを生成します。

import itertools

for item in itertools.product([1, 2], ['A', 'B']):
    print(item)
# (1, 'A'), (1, 'B'), (2, 'A'), (2, 'B')

8. permutations と combinations

順列と組み合わせを生成します。

import itertools

# 順列
for item in itertools.permutations([1, 2, 3], 2):
    print(item)
# (1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)

# 組み合わせ
for item in itertools.combinations([1, 2, 3], 2):
    print(item)
# (1, 2), (1, 3), (2, 3)

セクション6: copy モジュール

copy モジュールは、オブジェクトのコピーを作成するための関数を提供します。特に、浅いコピーと深いコピーの違いを理解することが重要です。

1. 浅いコピー (copy.copy)

浅いコピーは、オブジェクト自体をコピーしますが、オブジェクト内のネストされたオブジェクトはコピーされません。

import copy

original = [1, 2, [3, 4]]
shallow_copy = copy.copy(original)

print(original)  # [1, 2, [3, 4]]
print(shallow_copy)  # [1, 2, [3, 4]]

shallow_copy[2][0] = 'changed'
print(original)  # [1, 2, ['changed', 4]]
print(shallow_copy)  # [1, 2, ['changed', 4]]

2. 深いコピー (copy.deepcopy)

深いコピーは、オブジェクト自体とその内部のすべてのオブジェクトを再帰的にコピーします。

import copy

original = [1, 2, [3, 4]]
deep_copy = copy.deepcopy(original)

print(original)  # [1, 2, [3, 4]]
print(deep_copy)  # [1, 2, [3, 4]]

deep_copy[2][0] = 'changed'
print(original)  # [1, 2, [3, 4]]
print(deep_copy)  # [1, 2, ['changed', 4]]

まとめ

ここまでで、itertools モジュールと copy モジュールについて解説しました。これらのモジュールは、効率的なイテレータ操作やオブジェクトのコピー操作に非常に便利です。

この記事が気に入ったらサポートをしてみませんか?