Python 配列とリストの基本と活用法
Python 配列の基本概念とリストの特徴
Pythonでは、配列のような機能を持つデータ構造として主に「リスト」を使用します。リストは角括弧 []
で囲まれた要素のコレクションで、様々なデータ型の要素を格納できる柔軟性が特徴です。
リストの基本的な作成方法は以下のとおりです:
# 空のリストを作成
empty_list = []
# 要素を持つリストを作成
numbers = [1, 2, 3, 4, 5]
mixed_list = [1, "Hello", 3.14, True]
Pythonのリストは、他のプログラミング言語の配列と比較して以下の特徴があります:
- 異なるデータ型の要素を混在させることができる
- サイズが動的に変更可能(要素の追加・削除が容易)
- ネスト(入れ子)構造を作ることができる
- 豊富なメソッドとスライス操作が利用可能
リストの要素にアクセスするには、0から始まるインデックスを使用します:
my_list = [10, 20, 30, 40, 50]
print(my_list[0]) # 10を出力
print(my_list[2]) # 30を出力
負のインデックスを使用すると、リストの末尾から要素にアクセスできます:
print(my_list[-1]) # 50を出力(最後の要素)
print(my_list[-2]) # 40を出力(後ろから2番目の要素)
リストのサイズは len()
関数で取得できます:
print(len(my_list)) # 5を出力
Python リストを使った配列操作の基本テクニック
Pythonのリストでは、様々な操作を行うことができます。ここでは基本的なテクニックを紹介します。
要素の追加
リストに要素を追加するには、主に以下の方法があります:
# リストの末尾に要素を追加
my_list = [1, 2, 3]
my_list.append(4) # [1, 2, 3, 4]
# 特定の位置に要素を挿入
my_list.insert(1, 1.5) # [1, 1.5, 2, 3, 4]
# リストを結合
my_list.extend([5, 6]) # [1, 1.5, 2, 3, 4, 5, 6]
# +演算子でリストを連結
new_list = my_list + [7, 8] # [1, 1.5, 2, 3, 4, 5, 6, 7, 8]
要素の削除
要素を削除するための方法はいくつかあります:
my_list = [10, 20, 30, 40, 50, 30]
# インデックスを指定して削除
del my_list[1] # [10, 30, 40, 50, 30]
# 値を指定して最初に見つかった要素を削除
my_list.remove(30) # [10, 40, 50, 30]
# 末尾の要素を削除して返す
last_element = my_list.pop() # last_element = 30, my_list = [10, 40, 50]
# 特定のインデックスの要素を削除して返す
element = my_list.pop(1) # element = 40, my_list = [10, 50]
リストのスライス
スライスを使用すると、リストの一部を取得できます:
my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 開始インデックスから終了インデックスの手前まで
print(my_list[2:5]) # [2, 3, 4]
# 開始インデックスを省略すると最初から
print(my_list[:3]) # [0, 1, 2]
# 終了インデックスを省略すると最後まで
print(my_list[7:]) # [7, 8, 9]
# ステップ(間隔)を指定
print(my_list[1:8:2]) # [1, 3, 5, 7]
# 負のステップで逆順に取得
print(my_list[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
リストの変更
リストの要素は直接変更することができます:
my_list = [1, 2, 3, 4, 5]
my_list[2] = 30 # [1, 2, 30, 4, 5]
# スライスを使って複数の要素を一度に変更
my_list[1:4] = [20, 30, 40] # [1, 20, 30, 40, 5]
# 要素数が異なるリストで置き換えることも可能
my_list[1:4] = [200] # [1, 200, 5]
Python 配列の高度な操作とリストの活用例
基本操作を理解したら、より高度なリスト操作にも挑戦してみましょう。
リストの並べ替え
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
# 昇順に並べ替え(元のリストを変更)
my_list.sort() # [1, 1, 2, 3, 4, 5, 6, 9]
# 降順に並べ替え
my_list.sort(reverse=True) # [9, 6, 5, 4, 3, 2, 1, 1]
# 元のリストを変更せずにソートした新しいリストを取得
original = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_list = sorted(original) # sorted_list = [1, 1, 2, 3, 4, 5, 6, 9], original は変更されない
リスト内包表記
Pythonでは、リスト内包表記という簡潔な方法でリストを作成できます:
# 1から10までの2乗のリスト
squares = [x**2 for x in range(1, 11)] # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 条件付きリスト内包表記
even_squares = [x**2 for x in range(1, 11) if x % 2 == 0] # [4, 16, 36, 64, 100]
# 二重ループのリスト内包表記
pairs = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
# [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
多次元リスト(ネストされたリスト)
リストの要素としてリストを持つことで、多次元配列のような構造を作れます:
# 2x3の行列を表現
matrix = [
[1, 2, 3],
[4, 5, 6]
]
# 要素へのアクセス
print(matrix[0][1]) # 2(1行目、2列目)
# 行の追加
matrix.append([7, 8, 9]) # 3x3の行列になる
# 行列の転置(行と列を入れ替える)
transposed = [[row[i] for row in matrix] for i in range(3)]
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
リストとその他のデータ構造の連携
リストは他のデータ構造と組み合わせて使うことができます:
# リストからセットを作成(重複を削除)
my_list = [1, 2, 2, 3, 4, 4, 5]
unique_elements = set(my_list) # {1, 2, 3, 4, 5}
# リストから辞書を作成
keys = ['a', 'b', 'c']
values = [1, 2, 3]
dictionary = dict(zip(keys, values)) # {'a': 1, 'b': 2, 'c': 3}
# リストをタプルに変換(不変にする)
my_tuple = tuple(my_list) # (1, 2, 2, 3, 4, 4, 5)
Python 配列の代替手段とNumPyの活用
Pythonの標準リストは汎用性が高いですが、大量の数値データを扱う場合は効率が悪いことがあります。そこで登場するのが「NumPy」ライブラリです。NumPyは科学計算のための強力なライブラリで、効率的な多次元配列(ndarray)を提供します。
NumPy配列の基本
import numpy as np
# NumPy配列の作成
arr = np.array([1, 2, 3, 4, 5])
print(arr) # [1 2 3 4 5]
# 多次元配列の作成
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(matrix)
# [[1 2 3]
# [4 5 6]
# [7 8 9]]
# 特殊な配列の生成
zeros = np.zeros((3, 4)) # 3行4列の0で満たされた配列
ones = np.ones((2, 3)) # 2行3列の1で満たされた配列
identity = np.eye(3) # 3x3の単位行列
random_arr = np.random.random((2, 2)) # 2x2のランダム値配列
NumPy配列の操作
NumPy配列は標準のリストよりも高速で、ベクトル化された操作が可能です:
# 配列の演算
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a + b) # [5 7 9]
print(a * b) # [4 10 18]
print(a * 2) # [2 4 6]
print(np.dot(a, b)) # 32 (内積)
# 統計関数
arr = np.array([1, 2, 3, 4, 5])
print(np.mean(arr)) # 3.0 (平均)
print(np.median(arr)) # 3.0 (中央値)
print(np.std(arr)) # 1.4142... (標準偏差)
# 形状の変更
arr = np.arange(12) # [0 1 2 ... 11]
arr = arr.reshape(3, 4) # 3行4列に変形
NumPyはデータ解析、機械学習、科学計算など多くの分野で活用されています。標準のPythonリストと比較した主な利点は:
- メモリ効率が良い(同じデータ型の要素を連続したメモリに格納)
- 計算が高速(C言語で実装されたバックエンド)
- ベクトル化された操作(要素ごとのループを書かなくて良い)
- 高度な数学関数の豊富なライブラリ
Python 配列処理のパフォーマンス最適化とベストプラクティス
Pythonでリストや配列を扱う際、効率的なコードを書くためのベストプラクティスを紹介します。
メモリ効率を考慮したリスト操作
大きなリストを扱う場合、メモリ使用量を抑えるテクニックがあります:
# ジェネレータ式を使用(リスト内包表記よりメモリ効率が良い)
sum_of_squares = sum(x**2 for x in range(1000000))
# 不要になったリストは明示的に削除
big_list = [x for x in range(10000000)]
# 処理が終わったら
del big_list
# collections.dequeを使用(両端からの追加・削除が頻繁な場合)
from collections import deque
queue = deque([1, 2, 3])
queue.append(4) # 右端に追加
queue.appendleft(0) # 左端に追加
計算効率を高めるテクニック
# リストの結合は extend() を使う(+ 演算子より効率的)
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list1.extend(list2) # [1, 2, 3, 4, 5, 6]
# in 演算子の使用はセットの方が高速(リストは線形探索)
my_list = list(range(10000))
my_set = set(my_list)
# リストよりも高速
5000 in my_set # O(1)の時間複雑度
# リストは遅い
5000 in my_list # O(n)の時間複雑度
# 頻繁な連結操作には join() を使用
strings = ['a', 'b', 'c', 'd']
result = ''.join(strings) # 'abcd'
実務での応用例
実際のプロジェクトでは、以下のようなリスト・配列操作がよく使われます:
- データ前処理:
# 欠損値の除去 filtered_data = [x for x in data if x is not None] # 数値の正規化 normalized = [(x - min_val) / (max_val - min_val) for x in data]
- データ集計:
# グループごとの集計 from collections import defaultdict groups = defaultdict(list) for name, score in data: groups[name].append(score) # 各グループの平均を計算 averages = {name: sum(scores) / len(scores) for name, scores in groups.items()}
- データ変換:
# 辞書のリストからCSV形式に変換 import csv with open('output.csv', 'w', newline='') as f: writer = csv.DictWriter(f, fieldnames=['name', 'age', 'city']) writer.writeheader() writer.writerows(data_list)
パフォーマンス比較表
以下は、一般的な操作のパフォーマンス比較です:
操作 | リスト | NumPy配列 | 備考 |
---|---|---|---|
要素アクセス |