Самый эффективный способ сравнить / сопоставить два больших массива? - PullRequest
2 голосов
/ 06 октября 2010

Я пишу очень трудоемкую функцию в 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 ]

1 голос
/ 06 октября 2010
$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 перед тем, как стать циклом $people foreach, это означает, что вы продолжаете перезаписывать это значение всякий раз, когда у нового человека есть это ключевое слово.Другими словами, если первое лицо имеет ключевое слово «друг», тогда $matches["friendly friend of the friend company"] устанавливается на 3. Затем, если второе лицо имеет ключевое слово «дружественный», это значение перезаписывается и $matches["friendly friend of the friend company"] теперь равно 1.

Я думаю, вы хотели подсчитать сколько людей имеют ключевое слово, которое содержится в названии должности.В этом случае вместо подсчета того, сколько раз $keyword появляется в $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" */
        }
    }
}

Другая возможность заключается в том, чтоВы хотели знать , сколько ключевых слов было у данного человека, которое соответствует заданному названию должности.В этом случае вы бы хотели отдельный массив на человека.Это делается с небольшим изменением.

$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" */
        }
    }
}

Или, в качестве альтернативы, вы можете вернуться к подсчету, сколько раз ключевое слово соответствует сейчас, так как для каждого человека это на самом деле значимое значение ("how well соответствует ли задание ")

$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 */
        }
    }
}

По сути, прежде чем заняться проблемой создания цикла для повышения эффективности, вам необходимо выяснить, что именно ваш цикл действительно пытается выполнить.Подумайте об этом, и тогда вам лучше всего повысить эффективность, просто уменьшив количество итераций цикла до минимума и используя как можно больше встроенных функций, поскольку они реализованы в C (не интерпретируются и, следовательно, быстрее).беглый язык).

1 голос
/ 06 октября 2010

Вы можете использовать индекс слов в названиях должностей, чтобы сделать поиск более эффективным:

$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;
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...