字符串是否包含 PHP 中的任何子字符串列表?
Does a string contain any of a list of substrings in PHP?
我正在向应用程序添加一项功能,允许授权的石油钻井平台人员通过电子邮件向我们的系统提交天气报告(供我们的飞行员在计划飞行时使用)。棘手的部分是我们希望将这些报告与特定的石油平台相匹配,但人员(及其电子邮件帐户)可以在钻井平台之间移动。
我们已经有了一个 waypoints 列表,每个列表都有一个 "aliases" 字段。基本上,如果电子邮件主题在别名字段中包含某些内容,我们应该将电子邮件与该航路点相匹配。
主题可以是"Weather report 10 April @ 1100 Rig A for you as requested"
该航路点的别名类似于
"RRA RPA Rig A RigA"
请记住,我们拥有的所有其他 waypoints 都有一个类似的别名列表。
有没有比遍历每个别名的每个单词并检查它是否是电子邮件主题的子字符串更好的匹配方法?因为这听起来像是 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 实例,但是再一次,当一个简单的方法在实现的一小部分就足够时,这可能需要付出太多的努力时间.
我正在向应用程序添加一项功能,允许授权的石油钻井平台人员通过电子邮件向我们的系统提交天气报告(供我们的飞行员在计划飞行时使用)。棘手的部分是我们希望将这些报告与特定的石油平台相匹配,但人员(及其电子邮件帐户)可以在钻井平台之间移动。
我们已经有了一个 waypoints 列表,每个列表都有一个 "aliases" 字段。基本上,如果电子邮件主题在别名字段中包含某些内容,我们应该将电子邮件与该航路点相匹配。
主题可以是"Weather report 10 April @ 1100 Rig A for you as requested"
该航路点的别名类似于 "RRA RPA Rig A RigA"
请记住,我们拥有的所有其他 waypoints 都有一个类似的别名列表。
有没有比遍历每个别名的每个单词并检查它是否是电子邮件主题的子字符串更好的匹配方法?因为这听起来像是 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 实例,但是再一次,当一个简单的方法在实现的一小部分就足够时,这可能需要付出太多的努力时间.