计算两个词典中的闭合键和值集

时间:2013-07-25 19:14:33

标签: python recursion dictionary

我有一个通过程序运行的文件,用于根据公司名称和地址创建重复的组。如果发现记录具有相同的公司名称和地址,则会为其分配“欺骗组”编号。在第二遍中,我们仅根据电话号码创建欺骗组。这些电话号码欺骗也有一个欺骗组号,但在一个单独的领域。

我现在正在联系这两个欺骗组字段,以创建一个基于公司/地址和/或电话号码的单个组号码。

例如,如果在'123 Main St.'的'ABC公司'在该公司的dupe集团中有10条记录,其中一些记录有一个电话号码,该电话号码也在一个不同公司的骗子组中,在'456 South St'说“ABC公司”我想提供所有记录在两个欺骗组中都有一个id。

原始数据位于单个文件中,其中包含公司/地址欺骗字段和电话欺骗字段。

为此,我创建了两个词典。 一个是PhoneDupe字典,其中'key'是电话欺骗组号,'value'是该电话欺骗组内所有公司欺骗组的列表。

另一个是CompanyDupe dict,其中'key'是公司欺骗组号,'value'是该公司欺骗中所有电话欺诈组的列表。

这是一个小样本:

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],当我搜索第二个(8710)时,我会得到[7125,18684](我再次可以忽略7125因为我已经搜索过了)。

这必须一直来回,直到找到所有相关记录。

目标是最终得到应该合并的公司欺骗组列表。

我假设最好的方法是做某种递归函数,在收集所有记录之前一直回到第四位。我还需要传递已经搜索过的id列表。

有没有人知道以这种方式比较两个词典的好方法? 或者,如果有更好的方法可以做到这一点?

到目前为止,我试图将一个phonedupe id与两个dicts一起传递给一个函数,让它获取值然后将其传递回函数但是两个dicts反转然后查看第二个dict for phonedupe ID的。我也传递一个列表来收集已经搜索过的id或记录。最终它将达到无法找到列表中尚未存在的id的点,然后通过所有迭代返回列表以产生具有所有相关记录id的最终列表。

感谢。

修改 对不起,我的问题太长了,我想确保读者能够理解我的目的。

是的,我使用的小样本都是傻瓜。我抓住了我已经知道的所有记录,以确保它抓住了所有记录。我已经测试了我对完整数据的所有信息并且它正在运行。

因为每次我用函数调用函数时我都会反转两个字典,我添加了一个标志来检查字典的长度,所以我知道是否要添加到输出文件中。

当我第一次发布问题时,我没有任何代码可以进入这里,但我能够得到一些工作,所以我现在就发布它。在这种情况下,'pdupe'是电话欺骗,'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 = []

1 个答案:

答案 0 :(得分:0)

听起来您希望为c in C中的每个nc中的pPhoneDupes[n]中的每个co找到封闭式集CompanyDupes[n] st } 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

我们应该怎么做?可能完全相同:

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])])

你会注意到,实际上每个这样的集合都是相同的,并且似乎包含了样本输入中的每个数字。这就是找到闭集的本质 - 如果没有不相交的子集,那么实际上只有一个闭包。

让我们制作两个不相交的子集,看看会发生什么:

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)

如果您只想从CompanyDupes中获取值:

{{1}}