【发布时间】:2018-02-11 20:28:53
【问题描述】:
我有一个奇怪的要求,我需要从两个不同且非常大的列表中找到常见的“客户”。两个列表中的每个条目都是一个 Customer 对象,其中包含客户的名字和姓氏及其地址(按地址行细分,例如 address_line1、address_line2 等)。问题是任何一个列表中的数据都可能不完整,例如,对于第一个列表中的一条记录,客户的名字可能会丢失,而在第二个列表中,对于同一客户,他的地址(第 2 行和第 3 行)可能会丢失。我需要做的是找到两个列表中都存在的客户。需要注意的一点是列表可能很大。要记住的另一点是,名称和地址在语义上可能相同,但在您进行精确字符串匹配时可能不会返回结果。例如,在第一个列表中,第一个列表中客户的地址可以是B-502 ABC Street 的形式,而第二个列表中同一客户的地址可以是B 502 ABC Street 的形式。我使用编辑距离的原因是考虑到列表中的用户输入错误并处理两个列表中存在的数据中的某些其他细微差异
我所做的是在Customer类中实现eq函数如下
import re
import editdistance # Using this: https://pypi.python.org/pypi/editdistance
class Customer:
def __init__(self, fname, lname, address1, address2, address3, city):
# Removing special characters from all arguments and converting them to lower case
self.fname = re.sub("[^a-zA-Z0-9]", "", fname.lower())
self.lname = re.sub("[^a-zA-Z0-9]", "", lname.lower())
self.address1 = re.sub("[^a-zA-Z0-9]", "", address1.lower())
self.address2 = re.sub("[^a-zA-Z0-9]", "", address2.lower())
self.address3 = re.sub("[^a-zA-Z0-9]", "", address3.lower())
self.city = re.sub("[^a-zA-Z0-9]", "", city.lower())
def __eq__(self, other):
if self.lname == "" or self.lname != other.lname:
return False
t = 0
if self.fname != "" and other.fname != "" and self.fname[0] == other.fname[0]:
t += 1
if editdistance.eval(self.fname, other.fname) <= 2:
t += 3
if editdistance.eval(self.address1, other.address1) <= 3:
t += 1
if editdistance.eval(self.address2, other.address2) <= 3:
t += 1
if editdistance.eval(self.address3, other.address3) <= 3:
t += 1
if editdistance.eval(self.city, other.city) <= 2:
t += 1
if t >= 4:
return True
return False
def __hash__():
# TODO: Have a robust implementation of a hash function here. If two objects are "equal", their hashes should be the same
为了让客户同时出现在两个列表中,我将执行以下操作:
set(first_list).intersection(set(second_list))
但为了使其工作,客户对象需要是可散列的。
有人可以帮我提供一个好的散列机制吗?
【问题讨论】:
标签: python python-2.7 hash set set-intersection