0

会社名と住所に基づいて重複グループを作成するプログラムを実行するファイルがあります。レコードに同じ会社名と住所があることが判明した場合、それらには「重複グループ」番号が割り当てられます。2 番目のパスでは、電話番号のみに基づいて重複グループを作成します。これらの電話番号の複製には、複製グループ番号も与えられますが、別のフィールドにあります。

私は現在、これら 2 つのだまされたグループ フィールドを結合して、会社/住所および/または電話番号のいずれかに基づく単一のだまされたグループ番号を作成しようとしています。

たとえば、「123 Main St.」にある「ABC company」の場合 会社のだまされたグループに 10 件のレコードがあり、それらのレコードのいくつかには電話番号があり、その電話番号は別の会社のだまされたグループにもあり、「456 South St」の「ABC company」と言って、すべてのレコードを提供したい両方の重複グループで単一の ID。

元のデータは、会社/住所の重複用のフィールドと電話番号の重複用のフィールドを持つ単一のファイルにあります。

これを行うために、2 つの辞書を作成しました。1 つは PhoneDupe dict で、「キー」は電話のだましグループ番号で、「値」はその電話のだましグループ内にあるすべての会社のだましグループのリストです。

もう 1 つは CompanyDupe dict で、「キー」は会社の​​重複グループ番号であり、「値」はその会社の重複グループ内のすべての電話重複グループのリストです。

ここに小さなサンプルがあります:

PhoneDupes = {8715: [7125], 8710: [7125, 18684], 8719: [7067, 7101, 7125, 7342, 8068]}

CompanyDupes = {8068: [8719], 7342: [8719], 7125: [8719, 8715, 8710], 7067: [8719], 18684: [8710], 7101: [8719]}

この例では、PhoneDupes の最初の項目は #8715 で、値は 7125 です。次に、その値を取得して、CompanyDupes dict で検索する必要があります。これを行うと、7125 の値が [8719、8715、8710] であることがわかります。次に、これらの各値を取得する必要があります (8715 は既に検索したため、例外です)、PhoneDupe dict でそれらを検索します。最初 (8719) を検索すると [7067, 7101, 7125, 7342, 8068] が得られ、2 番目 (8710) を検索すると [7125, 18684] が得られます (ここでも、7125 は無視できます。私はすでにそれを検索しました)。

関連するすべてのレコードが見つかるまで、これを行ったり来たりしなければなりません。

目標は、組み合わせる必要がある会社のだまされたグループのリストのリストを作成することです。

これを行う最善の方法は、すべてのレコードが収集されるまで前後に移動し続ける何らかの再帰関数であると想定しています。また、すでに検索されている ID のリストを渡す必要があります。

このように2つの辞書を比較するための良いアプローチを知っている人はいますか? または、これを行うためのより良い方法があるかもしれませんか?

これまでのところ、1 つの phonedupe id を 2 つの dict と共に関数に渡し、値を取得してから関数に戻そうとしていますが、2 つの dict を逆にして、2 番目の dict で phonedupe id を調べます。また、既に検索された ID またはレコードを収集するためのリストを渡しています。最終的に、まだリストにない ID を見つけることができなくなり、すべての反復を通じてリストを元に戻して、関連するすべてのレコード ID を含む最終的なリストを生成するポイントに到達します。

ありがとう。

編集: 私の質問が長すぎて申し訳ありません。読者が私がやろうとしていることを理解できるようにしたかったのです。

はい、私が使用した小さなサンプルはすべてだまされています。だまされたとすでにわかっているすべてのレコードを取得して、それらすべてを取得したことを確認しました。私は完全なデータで私が持っているものをテストしましたが、それは機能しています。

関数内から関数を呼び出すたびに、2 つの辞書を逆にするため、辞書の長さをチェックするフラグを追加して、出力ファイルに追加するかどうかを確認します。

最初に質問を投稿したとき、ここに入力するコードはありませんでしたが、何かを機能させることができたので、今投稿します。この場合、「pdupe」は電話の dupe で、「dupe」は会社の​​ dupe です。

def test_rollup(id,comb_list,dict1,dict2,flag):
for dupe in dict1[id]:
    if dupe not in comb_list and comb_list != None:
        if flag == len(dict1):
            comb_list.append(dupe)
            test_rollup(dupe,comb_list,dict2,dict1,flag)
        else:
            test_rollup(dupe,comb_list,dict2,dict1,flag)
return comb_list

for id in pdupe:
    test_rollup(id,comb_list,pdupe,dupe,len(pdupe))
    if sorted(comb_list) not in master_list:
        master_list.append(sorted(comb_list))
    comb_list = []
4

1 に答える 1

0

each in 、 every in 、 every inも inの閉集合c in Cstを見つけたいようです。ncpPhoneDupes[n]coCompanyDupes[n]c

最初のパスとして、関連付けられていることがわかっている数のセットをいくつか作成しましょう。

PhoneDupes = {8715: [7125], 8710: [7125, 18684], 8719: [7067, 7101, 7125, 7342, 8068]}

CompanyDupes = {8068: [8719], 7342: [8719], 7125: [8719, 8715, 8710], 7067: [8719], 18684: [8710], 7101: [8719]}
[set([n]+PhoneDupes.get(n, [])+CompanyDupes.get(n, [])) for n in PhoneDupes]

これらはどうすればいいですか?おそらくまったく同じこと:

import itertools
def closure(inset, acc = set()):
    new = set(itertools.chain.from_iterable(itertools.chain(PhoneDupes.get(n, []),CompanyDupes.get(n, []))  for n in inset))
    really_new = (new - inset) - acc
    if not really_new: return inset|acc
    else: return closure(really_new, inset|acc)

closed_sets = [closure(set([n]+PhoneDupes.get(n, [])+CompanyDupes.get(n, []))) for n in PhoneDupes]
#=> [set([8068, 8710, 8715, 7342, 8719, 7125, 7067, 18684, 7101]), set([8068, 8710, 8715, 7342, 8719, 7125, 7067, 18684, 7101]), set([8068, 8710, 8715, 7342, 8719, 7125, 7067, 8684, 7101])]

closed_sets ==  [closure(s) for s in closed_sets]
#=> True

実際、そのようなセットはすべて同じであり、サンプル入力からのすべての数が含まれているように見えることに注意してください。これは、閉じたセットを見つける性質にあります。ばらばらのサブセットがない場合、実際にはクロージャは 1 つだけです。

互いに素な 2 つのサブセットを作成して、何が起こるか見てみましょう。

PhoneDupes2  = {k+1:[n+1 for n in v] for k,v in PhoneDupes.iteritems()}
CompanyDupes2  = {k+1:[n+1 for n in v] for k,v in CompanyDupes.iteritems()}
PhoneDupes.update(PhoneDupes2)
CompanyDupes.update(CompanyDupes2)
closed_sets = [closure(set([n]+PhoneDupes.get(n, [])+CompanyDupes.get(n, []))) for n in PhoneDupes]
#deduplicate closed_sets
frozenset(frozenset(s) for s in closed_sets)
#=> frozenset([frozenset([8068, 8710, 8715, 7342, 8719, 7125, 7067, 18684, 7101]), frozenset([8069, 8711, 8716, 7343, 8720, 7126, 7068, 18685, 7102])])

CompanyDupes から値のみを取得する場合:

def closure_co(inset, acc = set(), co_acc=set()):
    newphone = set(itertools.chain.from_iterable(PhoneDupes.get(n, []) for n in inset))
    newco = set(itertools.chain.from_iterable(CompanyDupes.get(n, [])  for n in inset))
    really_new = ((newphone|newco) - inset) - acc
    if not really_new: return co_acc
    else: return closure_co(really_new, inset|acc, co_acc|newco)
于 2013-07-25T23:51:21.857 に答える