0

すべてが一意の文字列である数千の名前を含む長いリストがありますが、類似した名前がある場合に 1 つだけが保持されるように、それらをフィルタリングして短いリストを作成したいと考えています。たとえば、元のリストには次のものが含まれる可能性があります。

ミッキーマウス

ミッキー・M・マウス

ミッキー・M・マウス

新しいリストには、そのうちの 1 つだけが含まれます。この時点でどれが重要であるかは問題ではありません。以下のコード ( abは比較対象のテキスト)を使用して類似性スコアを取得することができるため、適切な比率を選択すれば、包含/除外の決定を下すことができます。

difflib.SequenceMatcher(None, a, b).ratio()

私が苦労しているのは、最初のリストから2番目のリストを作成する方法です。些細なことだと思いますが、初心者の脳を困惑させます。

これに沿って何かがうまくいくと思っていたのですが、2番目のリストには何も入力されません。

for p in ppl1:
    for pp in ppl2:
       if difflib.SequenceMater(None, p, pp).ratio() <=0.9:
           ppl2.append(p)

実際、それがリストに入力されたとしても、それはまだ間違っています. 最初のリストの名前を 2 番目のリストのすべての名前と比較し、スコアの最も高い比率を追跡し、最高の比率がカットオフ基準を下回った場合にのみ追加する必要があると思います。

どんなガイダンスもありがたく受け取った!

4

2 に答える 2

1

これはあなたにとって高度すぎる可能性があるため、承認を得られないリスクがありますが、最適な解決策は次のとおりです。

あなたがやろうとしているのは、凝集クラスタリングの変種です。これを効率的に解決するには、union-find アルゴリズムを使用できますを使用して生成できる、異なる文字列aとのすべてのペアからb

def pairs(l):
    for i, a in enumerate(l):
        for j in range(i + 1, len(l)):
            yield (a, l[j])

類似率を持つペアをフィルタリングします<= .9

similar = ((a, b) for a, b in pairs
                  if difflib.SequenceMatcher(None, p, pp).ratio() <= .9)

次に、素集合の森でそれらを結合します。その後、セットをループして代表を取得します。

于 2013-05-20T11:15:24.657 に答える
0

まず、反復処理中にリストを変更しないでください。

1 つの戦略は、名前のすべてのペアを調べ、特定のペアが互いにあまりにも類似している場合は 1 つだけを保持し、2 つのペアが類似しなくなるまでこれを繰り返すことです。もちろん、結果はリストの最初の順序に依存しますが、データが十分にクラスター化されていて、類似度スコア メトリックが十分に優れていれば、探しているものが生成されるはずです。

于 2013-05-20T10:57:37.837 に答える