比较/匹配两个大型阵列的最有效方法?

时间:2010-10-06 16:37:05

标签: php algorithm compare

我在PHP中编写了一个非常流程密集的函数,需要尽可能优化速度,因为在极端情况下可能需要60秒才能完成。这是我的情况:

我正在尝试将一组人员与XML作业列表进行匹配。一系列人都有我已经分析过的关键字,用空格分隔。这些作业来自一个大型XML文件。

目前设置如下:

$matches = new array();
foreach($people as $person){
    foreach($jobs as $job){
        foreach($person['keywords'] as $keyword){
            $count = substr_count($job->title, $keyword);
            if($count > 0) $matches[$job->title] = $count;
        }
    }
}

我使用不同的类别对关键字循环几次。它完成了我需要它做的事情,但它感觉非常草率,并且这个过程可能需要非常长的时间,具体取决于人数/工作。

有更高效或更快的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以使用职位名称中的单词索引来提高查找效率:

$jobsByWords = array();
foreach ($jobs as &$job) {
    preg_match_all('/\w+/', strtolower($jobs->title), $words);
    foreach ($words[0] as $word) {
        if (!isset($jobsByWords[$word])) $jobsByWords[$word] = array();
        $jobsByWords[$word][] = &$job;
    }
}

然后,您只需迭代人员并检查关键字是否在索引中:

foreach ($people as $person) {
    foreach ($person['keywords'] as $keyword) {
        $keyword = strtolower($keyword);
        if (isset($jobsByWords[$keyword])) {
            foreach ($jobsByWords[$keyword] as &$job) {
                $matches[$job->title] = true;
            }
        }
    }
}

答案 1 :(得分:1)

$matches = new array();
foreach($people as $person){
    foreach($jobs as $job){
        foreach($person['keywords'] as $keyword){
            $count = substr_count($job->title, $keyword);
            if($count > 0) $matches[$job->title] = $count;
        }
    }
}

说实话,你的方法有点草率,但我认为这是因为你有一些特殊格式的数据,你必须解决?虽然不仅仅是草率,我看到你处理的东西中有一些丢失的数据,我认为这些内容并不是故意的。

我看到你不只是检查“是作业标题中的关键字”,而是“作业标题中关键字的次数”然后你存储了这个。这意味着对于职位名称friendly friend of the friend company,“关键字”朋友会显示3次,因此$matches["friendly friend of the friend company"] = 3。但是,由于您在成为$matches foreach循环之前声明$people,这意味着只要新人拥有该关键字,您就会继续覆盖此值。换句话说,如果第一个人有关键字“朋友”,则$matches["friendly friend of the friend company"]设置为3.然后,如果第二个人的关键字为“友好”,则此值将被覆盖并且$matches["friendly friend of the friend company"]现在为$keyword等于1。

我认为您想要做的是计算有多少人拥有职位名称中包含的关键字。在这种情况下,不应计算$job->title$matches = new array(); foreach($people as $person){ foreach($jobs as $job){ foreach($person['keywords'] as $keyword){ if(strpos($job->title, $keyword) !== FALSE) /* "If $keyword exists in $job->title" */ $matches[$job->title]++; /* Increment "number of people who match" */ } } } 出现的次数,而应该看到 if ,并做出相应的响应。

$matches = new array();
foreach($people as $person){
    $matches[$person] = new array();
    foreach($jobs as $job){
        foreach($person['keywords'] as $keyword){
            if(strpos($job->title, $keyword) !== FALSE) /* "If $keyword exists in $job->title" */
                $matches[$person][$job->title]++; /* Increment "number of keywords which match" */
        }
    }
}

另一种可能性是,您想知道给定人员匹配给定职位的多少关键字。在这种情况下,您需要每人一个单独的数组。这是通过稍作修改完成的。

$matches = new array();
foreach($people as $person){
    $matches[$person] = new array();
    foreach($jobs as $job){
        foreach($person['keywords'] as $keyword){
            if($count = substr_count($job->title, $keyword)) /* if(0) = false */
                $matches[$person][$job->title] += $count; /* Increase "number of keywords which match" by $count */
        }
    }
}

或者,或者,您可以返回计算关键字现在匹配的次数,因为每个人这实际上是一个有意义的值(“如何匹配”)

{{1}}

基本上,在解决使循环高效的问题之前,你需要弄清楚你的循环真正想要完成的是什么。弄清楚这一点,然后提高效率的最佳选择是将循环的迭代次数减少到最小并使用尽可能多的内置函数,因为它们是用C实现的(非解释因此更快) - 运行语言)。