Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで2つの数値リストの差分(欠落している数字)を見つける方法

はじめに

Pythonでは、2つのリストを比較して「片方には存在するが、もう片方には存在しない(または個数が足りない)要素」を見つけたい場面があります。本記事では、同じ数字の集合を表すはずの2つのリスト nums1nums2 が与えられたとき、互いに欠落している数字をすべて検出して出力するプログラムを紹介します。

ポイントは、要素が重複している場合でも正しく扱えることです。単純な集合の差分ではなく、各数字の出現回数(頻度)を比較することで、重複を含む欠落も正確に検出できます。

問題の例

例として、次の2つのリストを考えてみましょう。

nums1 = [4, 5, 8, 8, 6, 9]
nums2 = [3, 4, 4, 8, 8, 8, 6, 9, 5, 8]

この場合の出力は [3, 4, 8, 8] になります。理由は以下の通りです。

  • 3: nums1 には存在せず、nums2 に1つあるため、1つ欠落しています。
  • 4: 両方のリストに存在しますが、nums2 には2つ、nums1 には1つしかないため、1つ欠落しています。
  • 8: nums2 には4つありますが、nums1 には2つしかないため、2つ欠落しています。

このように、各数字について「両リスト間での出現回数の差」を求めれば、欠落している数字をすべて特定できます。

解決の手順

この問題は、次のステップで解くことができます。

  1. Counter を使って、nums1 の各要素の出現回数を記録した辞書 c1 を作成します。
  2. 同様に、nums2 の各要素の出現回数を記録した辞書 c2 を作成します。
  3. nums1 と nums2 に含まれるすべての異なる数字の集合 all_nums を作成します。
  4. 結果を格納する空のリスト res を用意します。
  5. all_nums の各数字 n について以下を判定します。
    • n が c1 に存在しない場合 → n を c2[n] 回だけ res に追加します。
    • n が c2 に存在しない場合 → n を c1[n] 回だけ res に追加します。
    • どちらにも存在する場合で、出現回数が異なるなら → n を |c1[n] − c2[n]| 回だけ res に追加します。
  6. 最後に res を返します。

実装コード

実際のPythonコードは次のようになります。標準ライブラリの collections.Counter を使うと、出現回数の集計を簡潔に書けます。

from collections import Counter

def solve(nums1, nums2):
    c1 = Counter(nums1)
    c2 = Counter(nums2)
    all_nums = set(nums1) | set(nums2)
    res = []
    for n in all_nums:
        if n not in c1:
            res = res + [n] * c2[n]
        elif n not in c2:
            res = res + [n] * c1[n]
        else:
            if c1[n] != c2[n]:
                res = res + [n] * abs(c1[n] - c2[n])
    return res

nums1 = [4, 5, 8, 8, 6, 9]
nums2 = [3, 4, 4, 8, 8, 8, 6, 9, 5, 8]
print(solve(nums1, nums2))

入力

[4,5,8,8,6,9], [3,4,4,8,8,8,6,9,5,8]

出力

[3, 4, 8, 8]

補足:より効率的な書き方

上記のコードでは res = res + [n] * count の形でリストを連結していますが、リストの連結は毎回新しいリストを生成するため、要素数が多い場合は非効率になります。実務では extend() メソッドや += 演算子を使うと、計算量を抑えられます。

def solve(nums1, nums2):
    c1 = Counter(nums1)
    c2 = Counter(nums2)
    all_nums = set(nums1) | set(nums2)
    res = []
    for n in all_nums:
        diff = abs(c1.get(n, 0) - c2.get(n, 0))
        if diff > 0:
            res.extend([n] * diff)
    return res

この書き方では dict.get(キー, デフォルト値) を使って存在しないキーの扱いを統一でき、コードもよりシンプルになります。

まとめ

2つのリスト間で欠落している数字を見つけるには、Counter による出現回数の集計と、各数字の頻度差の比較が有効です。重複要素がある場合でも正確に差分を検出できるため、データ照合や在庫管理のような実務的なシーンにも応用できます。

  1. 【Python入門】2つの文字列から珍しい単語(ユニークな単語)を見つけるプログラムの作り方

    はじめに この記事では、以下の問題文に対する解決方法を、実際のコード例とともにわかりやすく解説します。 問題文 2つの文字列が与えられたとき、その中から「珍しい単語」(どちらか一方の文字列にしか出現しない単語)をすべて抽出することを目標とします。両方の文字列に共通して含まれる単語は除外します。 解決のアプローチ ここでは辞書(dict)を使った出現回数のカウント方式を採用します。手順は次のとおりです。 空の辞書を用意する 各文字列をsplit()で単語ごとに分割する 各単語の出現回数を辞書に記録する 出現回数がちょうど1回の単語だけを結果として返す 実装例 # 珍しい単語を見つける関

  2. 【Python】2つのリスト間の欠落している値と追加されている値を見つける方法

    集合論において、ある集合Aの「補集合」とは、Aに含まれない要素を指します。また、集合Bに対するAの「相対補集合」は、集合AとBの「差(difference)」とも呼ばれます。本記事では、この原理を応用し、Pythonで2つのリストを比較することで、互いに欠落している要素と余分な要素を効率よく見つける方法を解説します。Pythonのset型には差分を求めるためのdifference()メソッドが標準で用意されており、これを使うと非常にシンプルに実装できます。 アルゴリズム ユーザー入力から2つのリストAとBを作成します。 AとBをそれぞれセット(set型)に変換します。 1つ目のリストに欠落し