我正在向应用程序添加功能,允许授权的石油钻机人员通过电子邮件向我们的系统提交天气报告(供飞行员在计划航班时使用)。棘手的部分是,我们希望将这些报告与特定的石油平台匹配,但是人员(及其电子邮件帐户)可以在钻机之间移动。
我们已经有了一个航路点列表,每个航路点都有一个“别名”字段。基本上,如果电子邮件主题在别名字段中包含某些内容,我们应该将电子邮件与该路标匹配。
主题可能是“ 4月10日的天气报告,按要求为您提供1100钻机A”
该航点的别名类似于“ RRA RPA Rig A RigA”
请记住,我们拥有的所有其他航路点都有类似的别名列表。
与遍历每个别名的每个单词并检查它是否是电子邮件主题的子字符串相比,有一种更好的匹配方法吗?因为这听起来像一个n ^ 2的问题。
另一种选择是我们施加限制,并告诉操作员他们必须将钻机名称放在主题的开头或结尾。
这听起来更像是算法问题,而不是PHP问题。看看What is the fastest substring search algorithm?
您可以将其转换为O(n log n)算法,但这取决于stripos()
的实现细节:
define('RIG_ID_1', 123);
define('RIG_ID_2', 456);
function get_rig_id($email_subject) {
$alias_map = [
'RRA' => RIG_ID_1,
'RPA' => RIG_ID_1,
'Rig A' => RIG_ID_1,
'RigA' => RIG_ID_1,
// ...
];
foreach(array_keys($alias_map) as $rig_substr) {
if(stripos($email_subject, $rig_substr) !== false) {
return $alias_map[$rig_substr];
}
}
return null;
}
这里每个子字符串由stripos()
精确检查一次。可能更好的解决方案是将这些字符串组成一系列正则表达式。在内部,正则表达式引擎能够非常有效地扫描文本,通常只扫描一次每个字符:
例如:
<?php
define('RIG_ID_1', 123);
define('RIG_ID_2', 456);
function get_rig_id($email_subject) {
$alias_map = [
'/RRA|RPA|Rig\\sA|RigA/i' => RIG_ID_1,
'/RRB|RPB|Rig\\sB|RigB/i' => RIG_ID_2,
// ...
];
foreach(array_keys($alias_map) as $rig_regex) {
if(preg_match($rig_regex, $email_subject)) {
return $alias_map[$rig_regex];
}
}
return null;
}
出于您的目的,实际的解决方案在很大程度上取决于您拥有多少台钻机,每个钻机拥有多少个子串。我怀疑除非您要处理数以万计的钻机,或者除非性能是此应用程序的关键方面,否则,天真的O(n ^ 2)解决方案可能就足够了。 (请记住,过早的优化是万恶之源!)一个简单的基准就可以证明这一点。
一个更好的解决方案,并且可能更快地,是建立一个Elasticsearch实例,但是再一次,当幼稚的方法在实现时间的一小部分就足够了时,这可能会花费很多精力。 >