1
0

ライブラリで優勝、Pythonでリスト内の重複した辞書を削除する

Last updated at Posted at 2024-09-05

やりたいこと

リストの中に入ってる複数の辞書が、キーと値が全て同じものであったら重複として削除したい

結論

unique_everseenを使用する。

pip install more-itertools

辞書の順番が異なっていたら別物として扱いたい場合

from more_itertools import unique_everseen

# [0]と[3]は区別する
target_list = [
    {"item1": "value1", "item4": "value4"},
    {"item2": "value2", "item5": "value5"},
    {"item3": "value3", "item5": "value5"},
    {"item4": "value4", "item1": "value1"},
]

list(unique_everseen(target_list))

辞書の順番が異なっていても、キーと値が同じなら同一として扱いたい場合

from more_itertools import unique_everseen

# [0]と[3]は同じとみなす
target_list = [
    {"item1": "value1", "item4": "value4"},
    {"item2": "value2", "item5": "value5"},
    {"item3": "value3", "item5": "value5"},
    {"item4": "value4", "item1": "value1"},
]

list(unique_everseen(target_list, key=lambda dict: frozenset(dict.items())))

補足

このケースにおいて考えられるパターンは以下2パターン。
どちらのケースにおいても、上記の実装は対応可能。

パターン1

単純なdict

target_list = [
    {"item1": "value1"},
    {"item2": "value2"},
    {"item3": "value3"},
    {"item1": "value1"},
]

パターン2

dictの中にさらにdictが含まれてるパターン

target_list = [
    {
        "item1": "value1",
        "item2": {
            "nest1": "nestValue1",
            "nest2": "nestValue2",
        }
    },
    {
        "item3": "value3",
        "item4": {
            "nest1": "nestValue1",
            "nest2": "nestValue2",
        }
    },
    {
        "item1": "value1",
        "item2": {
            "nest1": "nestValue1",
            "nest2": "nestValue2",
        }
    },
]

この関数知らなかったので、自作してた。。全然要らなかった。

# 重複する辞書を削除
unique_list = list(
    {convert_to_hashable(d): d for d in target_list}.values()
)

def convert_to_hashable(obj: Any) -> Union[tuple, Any]:
    """再帰的に辞書やリストをハッシュ可能な形式に変換する関数

    Args:
        obj (Any): 辞書やリスト、またはその他の型を受け付けます

    Returns:
        Union[tuple, Any]: タプルに変換されたハッシュ可能なオブジェクト、または元のオブジェクト
    """
    if isinstance(obj, dict):
        # 辞書のキーと値をソートしてタプルに変換し、frozendictに変換
        # ソートするので順番が異なる辞書も比較可能
        return tuple(
            (key, convert_to_hashable(value)) for key, value in sorted(obj.items())
        )

    elif isinstance(obj, list):
        # リスト内の要素もハッシュ可能にするため、リストを再起的にタプルに変換
        return tuple(convert_to_hashable(item) for item in obj)
    return obj
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0