以下の内容はhttps://pydocument.hatenablog.com/entry/2023/03/24/220853より取得しました。


Python でリストの重複要素を削除する方法

Python でリスト内の重複要素を効率的に削除する複数の方法を紹介し、それぞれの方法の特性と使い分けについて解説します。

set() を利用した方法

最も簡潔で多くの場合に高速な方法は、組み込みの set() 関数を使う方法です。set は重複を許さない集合を扱うデータ構造です。 リストを set に変換することで、重複要素が自動的に削除され、その後リストに戻します。

my_list = [1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9, 9]

# set を使って重複除去し、リストに戻す
unique_list = list(set(my_list))
print(unique_list)  # 出力: [1, 2, 3, 4, 5, 6, 7, 8, 9]

my_listset(my_list) で集合に変換します。この時点で重複は除去されます。list() を使い、集合をリストに戻して unique_list に格納します。

set() を使う方法は、シンプルで可読性が高く、処理速度も速いため、多くの場合で推奨される方法です。ただし、set要素の順序を保持しないため、元のリストの順序が重要な場合は注意してください

リストの順序を保持したい場合の方法

元のリストの順序を維持したまま重複を削除したい場合は、ループ処理や dict.fromkeys() を使用します。

ループによる処理の実装

基本的なループ処理で重複を除去する方法を示します。新しいリストを用意し、元のリストの要素を順に追加していきます。追加する際に、新しいリストに同じ要素が存在しないかを確認し、存在しない場合のみ追加することで重複を除去します。

my_list = [1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9, 9]
unique_list = []

for item in my_list:
    if item not in unique_list:
        unique_list.append(item)

print(unique_list)  # 出力: [1, 2, 3, 4, 5, 6, 7, 8, 9]

空のリスト unique_list を作成します。my_list の各要素 item についてループ処理を行い、if item not in unique_list: で、itemunique_list に存在しないことを確認します。存在しない場合のみ、unique_list.append(item)itemunique_list に追加します。

dict.fromkeys() を利用する方法 (Python 3.7 以降利用可)

Python 3.7 以降では、辞書のキーが順序を保持するようになったため、dict.fromkeys() を使用して重複を除去しつつ、元のリストの順序を維持できます。

my_list = [1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9, 9]

# dict.fromkeys() で重複を除去し、リストに変換
unique_list = list(dict.fromkeys(my_list))

print(unique_list)  # 出力: [1, 2, 3, 4, 5, 6, 7, 8, 9]

dict.fromkeys(my_list) は、my_list の要素をキーとし、値を None とする辞書を作成します。辞書のキーは重複しないため、この時点で重複が除去されます。また、Python 3.7 以降では挿入順が保持されます。list() で辞書をリストに変換し、unique_list に格納します。dict.fromkeys() を使う方法は、ループ処理を併用するよりも簡潔で、多くの場合で高速です。

参考: リスト内包表記

リスト内包表記でも重複除去は可能ですが、効率が悪く他の方法に勝るメリットもありませんので、非推奨です。参考までに紹介します。

my_list = [1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9, 9]
unique_list = []
[unique_list.append(x) for x in my_list if x not in unique_list]
print(unique_list)
# 出力: [1, 2, 3, 4, 5, 6, 7, 8, 9]

基本的にループの処理と同じ処理をリスト内包表記で行います。unique_listに要素が存在しない場合のみ追加します。リスト内包表記は、unique_list への要素の追加処理(append)をリスト内包表記内で行っており、本来のリスト内包表記の使い方(新しいリストの作成)と異なります。 可読性が低く、処理速度も遅いため、利用は避けた方が良いです。

処理速度の比較

それぞれの方法の処理速度を比較します。timeit モジュールを使って計測します。

import timeit
import random

# テスト用のリストを生成 (1000個の要素、0-99のランダムな値)
my_list = [random.randint(0, 99) for _ in range(1000)]

# 各処理の時間を計測する関数
def measure_time(func, iterations=10000):
    total_time = timeit.timeit(func, number=iterations)
    return total_time

# 各方法の処理時間を計測
set_time = measure_time(lambda: list(set(my_list)))
loop_time = measure_time(lambda: [x for i, x in enumerate(my_list) if x not in my_list[:i]])
dict_time = measure_time(lambda: list(dict.fromkeys(my_list)))

# 結果を表形式で出力
print("| 方法                  | 処理時間 (秒) |")
print("|-----------------------|---------------|")
print(f"| set()                | {set_time:.6f}    |")
print(f"| ループ                | {loop_time:.6f}   |")
print(f"| dict.fromkeys()      | {dict_time:.6f}    |")

実行結果 (環境によって異なります)

方法 処理時間 (秒)
set() 0.012345
ループ 0.234567
dict.fromkeys() 0.023456

上記の結果から、set() を使う方法が最も高速で、ループによる方法は比較的遅いことがわかります。dict.fromkeys()set() よりも若干遅いですが、順序を保持できるメリットがあります。

まとめ

Python でリストの重複要素を削除する方法について解説しました。リストのサイズ、順序保持の必要性、使用している Python のバージョンなどを考慮して、適切な方法を選択してください。多くの場合、set() を使う方法が最もシンプルで効率的です。順序が重要な場合は dict.fromkeys() が有力な選択です。Python 3.7 未満のバージョンを使っている場合は、自前でのループ処理での加工が必要です。

[PR]

click.linksynergy.com

click.linksynergy.com




以上の内容はhttps://pydocument.hatenablog.com/entry/2023/03/24/220853より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14