Сопоставление значений массива со строкой PHP



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



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



Я попробовал 2 методы для сопоставления массива.
1) я stringx преобразовать в массив с помощью взорваться(" ", $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 струны по одной за раз.



Помощь очень ценится.

688   6  

6 ответов:

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

Он выполняет 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);
}

Другой пример, который работает немного быстрее (107ops/s с 15kb string и 10k words dictionary)

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);
}

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

Вот так:

foreach ($array_10000 as $word)
{
    if (stripos($stringx, $word) !== false)
    {
        // do your stuff
    }
}

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

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

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

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

Я не проверял это, но это просто произошло со мной:

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

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

Вы можете просто сделать 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.

Comments

    Ничего не найдено.