efrolov54rus
@efrolov54rus
Младший Web-разработчик (принимаю заказы)

Как сделать быстрый поиск строки по подстроке в большом файле на PHP?

День добрый! Возникла довольно простая (вероятно слишком простая) задача для хорошего программиста, но я к сожалению пока только учусь, поэтому нужна ваша помощь :o
1. Есть большой CSV файл (около 2-5мб), нужно прочитать его с минимальным расходом памяти на сервере (например, с помощью чанков)
2. Во время чтения, превращать строку во временный массив, не дожидаясь окончания чтения
3. Временный массив поместить в цикл, в котором по второму столбцу сравнивать значение с Query (см. комментарии в примере кода ниже)
4. Если значение совпадает, вернуть всю строку, содержащую это значение

Пробовал вот так, но не совсем понимаю как оно должно работать:

function csvToArray($file, $delimiter)
    {
        $data = array();
        
        $file = fopen($file, 'r');
        
        $iterator = 0;
        $header = null;
        
        while (($row = fgetcsv($file, 1000, $delimiter)) !== false)
        {
            $is_mul_1000 = false;
            if(!$header){
                $header = $row;
            }
            else{
                $iterator++;
                $data[] = array_combine($header, $row);
                if($iterator != 0 && $iterator % 1000 == 0){
                    $is_mul_1000 = true;
                    $chunk = $data;
                    $data = array();
                    yield $chunk;
                }
            }
        }
        fclose($file);
        if(!$is_mul_1000){
            yield $data;
        }
        return;
    }

foreach(csvToArray('/home/catalog_new.csv', "\n") as $key => $data){
    $key = array_values(array_slice($data[$key], -1))[0]; // выбирает первый столбец для поиска по нему (по задумке)
    
    $search = 'РО-65443'; // строка для поиска
    
        $buffer = explode('-', $key); // делим на две части
        foreach($buffer as $name){
             // Ищем по первой и второй части
            if(!empty($name) && stripos($search, $name) !== false || $search == $name){
                echo $data; // выводим строку на экран, подстрока которой, полностью или частично совпадает
            }
        }
    }
   
}


Сам CSV выглядит как-то так:

1,"RZ-541-REV2|RZ-541-REV1.5|RZ-541-TEST",1,1
2,"МК-65530-RU|МК-65530-KZ|МК-65530-TEST",1,2
  • Вопрос задан
  • 543 просмотра
Решения вопроса 2
@ComodoHacker
В базу его засуньте. Это работа как раз для нее.
Ответ написан
Комментировать
FanatPHP
@FanatPHP
Чебуратор тега РНР
То что ComodoHacker написал.

Ну или
shell_exec("grep ". escapeshellarg($podstroka)." ". $filename);
- самый оптимальный вариант (после базы данных)

Если же будешь костылить сам, то имей в виду, fgetcsv примерно в 40 раз медленнее тупого exolode (дада, я сама офигела!). и если у тебя нет сложных данных (кавычек, переносов строк), то стоит подумать о замене.

Только ради бога, сделай лицо попроще. Ты УЖЕ читаешь построчно. Нет НИ МАЛЕЙШЕЙ причины отдвать результат "чанками" и дальше возиться совсеми slice values. Выкини всю эту красоту, и сделай обычный цикл с while
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы