鉴于每个公司的分机位数可能不同,并且每个国家和地区代码的号码中的位数可能不同,因此要有效地解决这个问题是一个棘手的问题。
即使您将数据表拆分为基数和扩展名,您仍然必须将传入的数字拆分为基数和扩展名,我实际上认为这会使事情复杂化。
我倾向于尝试的是:
原始格式
- 尝试将传入号码与数据库匹配。
- 如果它与一条记录匹配,您就会得到答案 - 一个特定的人。
- 如果它匹配多个记录,则出现问题,因此失败。
- 否则,您必须找到公司:
- 从传入号码中去掉尾随数字,并再次尝试将其与数据库匹配。
- 如果位数低于阈值(可能是 6 位数),那么您的搜索可能会失败。这只是为了限制在找不到数字时执行的数据库搜索的数量。
- 如果它没有匹配任何记录,那么您需要再次尝试此步骤。
- 如果它匹配多个记录,则出现问题,因此失败。
- 如果它与一条记录完全匹配,那么您将获得下一个最佳答案 - 公司。
例如,搜索“+43123456777”:
- +43123456777 匹配 0 个条目。
- +4312345677 匹配 0 个条目。
- +431234567 匹配 1 个条目:“A 公司”
这种方法的主要失败模式是公司是否有可变长度的扩展号码。例如,考虑如果 431234567890 和 43123456789 都是有效数字但只有第二个在数据库中会发生什么。如果来电号码是 431234567890,那么 43123456789 会匹配错误。
拆分格式
这有点复杂,但更健壮。
- 尝试将传入号码与数据库匹配。
- 如果它与一条记录匹配,那么您就有了答案——公司。
- 如果匹配多条记录,匹配不带扩展名的条目,您就找到了该公司。
- 否则,您必须找到基本公司编号和分机:
- 从传入号码中去掉尾随数字,并再次尝试将其与数据库匹配。
- 如果位数低于阈值(可能是 6 位数),那么您的搜索可能会失败。这只是为了限制在找不到数字时执行的数据库搜索的数量。
- 如果它没有匹配任何记录,那么您需要再次尝试此步骤。
- 如果它与一条记录匹配,那么您已经找到了答案 - 公司。
- 如果它匹配多条记录,那么您已经找到了公司的基本号码,因此现在知道了分机号,因此可以尝试查找特定的人:
- 从原始传入号码的开头剥离基数,并使用它来搜索具有该基数的记录的扩展名。
- 如果它与一条记录完全匹配,则您已找到特定的人。
- 如果它不匹配特定的人,匹配不带扩展名的条目,您就找到了公司。
例如,搜索“+43123456777”:
- +43123456777 匹配 0 个条目。
- +4312345677 匹配 0 个条目。
- +431234567 匹配 2 个条目:“empty:Company A”和“890:employee in company A”
- 在这两个匹配项中,“77”不匹配任何内容,因此返回空扩展名:“Company A”。
实施说明
如上所述,该算法确实存在一些效率问题。如果数据库查找开销很大,它与电话号码的长度有一个线性成本,特别是在数据库中不存在类似号码的情况下(例如,如果传入的号码来自哈萨克斯坦,但没有哈萨克斯坦数据库中的数字 *8')。
不过,您可以相对容易地添加一些优化。如果与您打交道的大多数公司都使用 3 或 4 位扩展名,那么您可以先从末尾剥离 4 位数字,然后进行二进制切分,直到找到答案。在许多情况下,这会将 15 位数字减少到 4 或 5 个,最多 6 次查找。
此外,每次缩小选择范围时,您只能在前一个选择范围内进行选择,而不必在整个数据库中进行选择。
附加实施说明
终于弄清楚了Unreason 的答案是如何工作的,我可以看到这是一个更简单、更优雅的解决方案。我希望我只是简单地在传入号码中查找数据库号码,而不是相反。
我唯一担心的是,telephonenumber
对数据库中的每一个都执行此操作可能会对服务器产生过多的要求。我建议在最大压力下对该解决方案进行基准测试,看看它是否会导致问题。如果没有,很好 - 使用它。如果是这样,请考虑实现我的算法的简单形式并再次进行压力测试。如果性能仍然太低,请尝试我的二分搜索建议。