HOWTO · Python
Python でリストの要素を交換する
このチュートリアルでは、Python でリストの要素を交換する方法を示します。
このページの内容
Python のリストで要素を交換すると、それぞれの位置にある値が入れ替わります。Python のタプルアンパッキングを使うと、2つの要素を簡潔に交換できます。テンポラリ変数を使えば代入の手順が明確になり、pop() と insert() を使う方法では、値をリストから取り出して別の位置へ移します。2つの位置だけを交換するのではなく範囲全体を反転したい場合は、スライス代入が便利です。
タプルアンパッキングでリストの要素を交換する
タプルアンパッキングでは、左辺のインデックス指定先に値を代入する前に、右辺の値が評価されます。そのため、別の保存用変数を使わずに、それぞれの位置へもう一方の位置に元々あった値を代入できます。Python のリストのインデックスは0から始まるため、最初の要素のインデックスは 0 です。
位置が2つ決まっている場合は、次のように直接代入します。例を実行してください。最初の例では色を表す英語の値と出力がそのまま表示されます。
このセクションのコードと表示されるラベルや出力は英語のままです。
items = ["red", "blue", "green", "gold"]
items[1], items[3] = items[3], items[1]
print(items)
['red', 'gold', 'green', 'blue']
これにより、2番目と4番目の値がリスト内で交換されます。リストの長さは変わらず、指定したインデックス以外の要素も元の位置に残ります。
独立したペアを複数交換するには、インデックスのペアを反復可能なオブジェクトにまとめ、各ペアに同じ代入を適用します。
items = [6, 2, 7, 8, 5, 9, 10, 3]
for left, right in [(0, 3), (4, 6)]:
items[left], items[right] = items[right], items[left]
print(items)
[8, 2, 7, 6, 10, 9, 5, 3]
各反復では、その時点のリストの値を使って1組を交換します。インデックスが意図した位置を指すペアを選んでください。ペア同士でインデックスが重複している場合、先の交換によって後の交換で参照する値が変わることがあります。
テンポラリ変数を使って要素を交換する
テンポラリ変数を使うと、交換に必要な3つの代入が明確になります。まず一方の値を保存し、次にそのリスト上の位置をもう一方の値で上書きし、最後に保存した値を2つ目の位置へ代入します。手順を明示することで、周囲の処理を追いやすくなる場合に便利です。
このセクションのコードと表示されるラベルや出力は英語のままです。
items = [6, 2, 7, 8]
temp = items[1]
items[1] = items[3]
items[3] = temp
print(items)
テンポラリ変数には、リスト内の元の位置を上書きする前に値を保存しておく必要があります。単純なペアの交換ならタプルアンパッキングのほうが短く書けます。どちらの方法でも既存のリストが更新されます。
pop() と insert() で要素を交換する
pop() は、項目を削除してその値を返すリストのメソッドです。項目を削除すると後続の要素は左に1つ移動するため、削除後のインデックスは別の値を指すことがあります。insert() もリストのメソッドで、指定した位置の前に値を挿入し、後続の要素を右に移動させます。
元々インデックス 1 と 3 にあった値を交換するには、まず小さいほうのインデックスから削除します。すると、元々インデックス 3 にあった値はインデックス 2 に移動します。
このセクションのコードと表示されるラベルや出力は英語のままです。
items = [6, 2, 7, 8]
first = items.pop(1)
second = items.pop(2)
items.insert(1, second)
items.insert(3, first)
print(items)
2回目の pop() では、最初の削除によって残りの要素が移動したため、インデックス 2 を使います。2つの値を削除した後、それぞれを位置 1 と 3 に挿入すると、リストの長さを元に戻しながらペアを交換できます。直接代入より手順が多いため、削除と再挿入がもともとの処理に含まれる場合に主に適しています。
スライスを反転して要素の範囲を交換する
スライスでは start:stop:step を使って範囲を指定します。開始インデックスは含まれますが、終了インデックスは含まれません。負のステップを指定すると、選択した値を逆順にたどります。スライス代入は、リスト内の選択範囲を別のシーケンスで置き換えます。
このセクションのコードと表示されるラベルや出力は英語のままです。
items = [6, 2, 7, 8]
items[1:4] = items[1:4][::-1]
print(items)
ここでは選択範囲にインデックス 1、2、3 の要素が含まれるため、代入によって3つすべての値が逆順になります。両端の値だけを交換する処理ではありません。範囲を反転して隣り合う2つの値だけを交換するには、2要素の範囲を選択します。離れた2つのインデックスの値を交換するなら、タプルアンパッキングのほうが明快です。
方法を選び、インデックスを確認する
2つの要素を直接交換するにはタプルアンパッキングを使い、独立した複数の交換にはインデックスのペアを反復するループを使います。明示的な手順によって周囲のコードを説明しやすくなる場合は、テンポラリ変数を使います。pop() と insert() は、値の削除や追加に伴ってリスト内の位置を変えるため、削除のたびにインデックスを確認し直してください。選択した範囲を反転することが目的なら、スライス代入を使います。
リストのインデックスは 0 から始まります。有効な範囲外のインデックスで要素を読み取ったり代入したりすると、IndexError が発生します。交換する前に、各インデックスがリストの有効範囲内にあり、交換したい値の位置を指していることを確認してください。インデックスがユーザー入力やほかのデータから計算される場合は、特にこの確認が役立ちます。