Сопоставление значений массива со строкой PHP - PullRequest
3 голосов
/ 24 марта 2011

Я работаю над небольшим проектом, и мне нужна помощь.У меня есть файл CSV с 150000 строк (каждая строка имеет 10 столбцов данных).Я использую fscvread для чтения файла, и во время цикла я хочу сопоставить один из столбцов (назовем его stringx) каждой строки с массивом из 10000 слов.Если какое-либо из 10000 слов существует в stringx, оно удаляется с помощью preg_replace.

Теперь все в порядке.У меня все работает нормально, но проблема в том, что он слишком медленный.

Я пробовал 2 метода, чтобы соответствовать массиву.1) Я конвертирую stringx в массив, используя explode ("", $ stringx), а затем использую array_diff ($ array_stringx, $ array_10000);2) использовать foreach для $ array_10000 и preg_replace для $ stringx

Метод 1 занимает около 60 секунд, чтобы пройти 200 строк данных, а метод 2 может зациклить 500 строк за 60 секунд.лучший способ сделать это?

Еще раз, я ищу эффективный способ (в основном) array_diff массива из 10 000 слов против 150 000 строк по одной за раз.

Помощь очень многооценены.

Ответы [ 6 ]

2 голосов
/ 24 марта 2011

Следующее является просто альтернативой.Он может или не может удовлетворить ваши требования.

Он выполняет 84 операции в секунду со словарем 10k слов и строкой 15k на моем ноутбуке.

Недостатком является то, что он не удаляет пробелы вокруг слов.

$ wordlist - это просто строки по одному слову в каждой, это может быть файл.

$dict = array_flip(preg_split('/\n/',$wordlist));

function filter($str,$dict) {
  $words = preg_split('/\s/',$str);
  sort($words);
  $words = array_unique($words);

  foreach ($words as $word) {
    if (key_exists($word,$dict)) {
        $removeWords[] = '/\b' . $word . '\b/';
    }
  }
  return preg_replace($removeWords, '', $str);
}

Еще один пример, который работает немного быстрее (107op / s со строкой 15kb и словарем 10k слов)

function filter2($str,$dict) {
  $words = preg_split('/\b/',$str);
  foreach ($words as $k => $word) {
    if (key_exists($word,$dict)) {
        unset($words[$k]);
    }
  }
  return implode('', $words);
}
1 голос
/ 24 марта 2011

Как насчет того, чтобы не взорвать stringx и выполнить stripos () для каждого слова в $ array_10000?

как это:

foreach ($array_10000 as $word)
{
    if (stripos($stringx, $word) !== false)
    {
        // do your stuff
    }
}
1 голос
/ 24 марта 2011

PHP не язык для скорости, но я думаю, вы это знаете. Я должен сделать что-то подобное в проекте, который я пишу, и я пишу файл на PHP, затем использую автономный Matlab, чтобы прочитать этот файл, обработать его и вывести другой.

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

1 голос
/ 24 марта 2011

Ваш 10000 слов отсортирован?Если нет, попробуйте сначала отсортировать его.

Редактировать: хорошо, так как он отсортирован, я предполагаю, что, возможно, PHP array_search не выполняет бинарный поиск, поэтому я бы искал реализацию бинарного поиска и использовал ее.Если на самом деле это просто линейный поиск, то вы получите увеличение скорости на порядок.

0 голосов
/ 08 июля 2015

Вы можете просто сделать foreach, а также implode.

$words = array("one","two", "three");
$number = 0;
foreach ($words as $false_array)
{
$number += 1;
$array[$number] = $false_array;
echo "Added ". $false_array . ". ";
}
foreach ($words as $false_array)
{
echo "Array Contains " . $false_array . ". ";
}

Если вы выполните это в php, вы получите:

Added one. Added two. Added three. Array Contains one. Array Contains two. Array Contains three.
0 голосов
/ 24 марта 2011

Я не проверял это, но мне пришло в голову:

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

Надеюсь, это поможет!Ура!

...