PHP - 匹配字符串与最佳部分匹配

时间:2015-07-20 17:11:00

标签: php performance csv pattern-matching

我有一个CSV文件,其中包含第一列中的部分(或完整,可变长度)英国邮政编码,以及后续列中的各种关税信息。

我有一个网站表格,要求用户输入完整的英国邮政编码。

然后,应用程序需要根据CSV文件找到与其邮政编码最佳匹配。匹配记录的所有字符必须在其实际邮政编码中,并且为此目的的最佳匹配将是来自具有相同顺序的邮政编码的最多字符的CSV的匹配,并且没有在邮政编码中没有的字符

我已经玩过将这些CSV数据添加到mysql数据库中,但我不认为(如果错误请纠正我)它会更有效率。

CSV文件包含与之匹配的不同长度的邮政编码。

E.g。

B1(应该是从B1开始的任何地方的匹配,其他地方没有更精确的匹配)

<input id="assessmentId" type="hidden" value="<c:out escapeXml="true" value="${param.assessmentId}" />" />
<input id="classroomId" type="hidden" value="<c:out escapeXml="true" value="${param.classroomId}" />" />




console.log($("#assessmentId").val()) // 206a9246
console.log($("#classroomId").val())  // 722bfadb

因此邮政编码B1 2NB应与第一个条目匹配。 B12 1NB也应该与第一个例子相匹配。 B13 2PQ将匹配第二个例子。

基本上我需要在CSV文件中搜索最接近的匹配项,然后将整行加载到可用于进一步计算的数组中。

这样做最有效的方法是什么? 假设将整个CSV加载到内存中不是最好的方法吗?

1 个答案:

答案 0 :(得分:1)

大约有1,000行,让我们说每行50-100字节的数据,只有&#34;只有&#34; 50k-100k的内存,并没有那么多。

PHP op-caching相当不错,因此APC或Zend OpCache将在内存中完成所有&#34;&#34;缓存您需要的,只要您的文件是PHP,而不是从&amp;每次解析CSV。

虽然数据库确实具有更高的可扩展性,但TCP连接和网络延迟的开销可能无法使其性能最高。

我提供此代码示例作为实现此 IF 的方法,您决定内存中的PHP解决方案最适合您。

<?php

/**
 * Class PostcodeLookup
 *
 * Keeping the lookup data in a PHP file like this means that it will be cached in memory by APC or OpCache
 */
class PostcodeLookup
{

    /**
     * This will contain our lookup data and payload
     *
     * @var array
     */
    private $arr_pc = [];

    /**
     * Populate the lookup array on construction
     */
    public function __construct()
    {
        $this->arr_pc = [
            'M1' => 'test1',
            'M12' => 'test2',
            'M123' => 'test3',
            'G1' => 'test4',
            'G2' => 'test5',
        ];
    }

    /**
     * Our public function for running lookups
     *
     * This is here so we normalise the data ONCE and strlen() ONCE
     *
     * @param $str_pc
     * @return bool
     */
    public function run($str_pc)
    {
        $str_normalised = strtoupper(str_replace(' ', '', $str_pc));
        return $this->check($str_normalised, strlen($str_normalised));
    }

    /**
     * Reducing, recursive lookup
     *
     * @param $str_pc
     * @param $int_length
     * @return bool
     */
    private function check($str_pc, $int_length)
    {
        if(isset($this->arr_pc[$str_pc])) {
            return $this->arr_pc[$str_pc];
        }
        return $int_length > 1 ? $this->check(substr($str_pc, 0, -1), --$int_length) : false;
    }
}

// Some example usage
$obj_lookup = new PostcodeLookup();
var_dump($obj_lookup->run('M123'));
var_dump($obj_lookup->run('M1'));
var_dump($obj_lookup->run('M19999'));
var_dump($obj_lookup->run('G2'));