【问题标题】:Does a string contain any of a list of substrings in PHP?字符串是否包含 PHP 中的任何子字符串列表?
【发布时间】:2020-07-31 13:41:54
【问题描述】:

我正在向应用程序添加一项功能,该功能允许授权的石油钻井平台人员通过电子邮件向我们的系统提交天气报告(供我们的飞行员在计划飞行时使用)。棘手的部分是我们希望将这些报告与特定的石油平台相匹配,但人员(及其电子邮件帐户)可以在钻井平台之间移动。

我们已经有一个航点列表,每个航点都有一个“别名”字段。基本上,如果电子邮件主题在别名字段中包含某些内容,我们应该将电子邮件与该航路点匹配。

主题可以是“根据要求为您提供 4 月 10 日 @ 1100 Rig A 的天气报告”

该航路点的别名类似于 “RRA RPA Rig A RigA”

请记住,我们拥有的所有其他航路点都有一个类似的别名列表。

有没有比遍历每个别名的每个单词并检查它是否是电子邮件主题的子字符串更好的匹配方法?因为这听起来像是一个 n^2 的问题。

另一种方法是我们设置限制并告诉操作员他们必须将钻机名称放在主题的开头或结尾。

【问题讨论】:

  • 将列表转换为正则表达式/RRA|RPA|Rig A|RigA/,然后进行正则表达式匹配。
  • PCRE 引擎在优化工作方面会比没有 CompSci 硕士学位的任何人做得更好。对列表中的每个项目使用preg_quote(),然后使用implode() 创建表达式。
  • 尽管从长远来看,为请求执行标准格式可能会更好地为您服务。试图用用户决定输入的每一个奇怪的东西来玩打地鼠永远不会有效地利用任何人的时间。
  • 通过强制执行标准格式,我们总是可以退回到不匹配航路点但无论如何让它通过,这不是很好,但我可以说服老板没问题。我喜欢正则表达式技巧,我希望有类似的东西我不知道!

标签: php string matching


【解决方案1】:

这听起来更像是一个算法问题,而不是 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) 解决方案可能就足够了。 (请记住,过早的优化是万恶之源!)一个简单的基准就可以证明这一点。

一个更好的解决方案 - 并且可能更快 - 是设置一个弹性搜索实例,但是当一个简单的方法在一小部分实施时间内就足够了时,这可能会再一次付出太多的努力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-06
    • 1970-01-01
    • 2015-03-24
    • 1970-01-01
    • 2014-08-09
    • 2012-11-15
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多