Как это можно оптимизировать:
- Инструкции предельного количества, которые необходимо выполнить для каждой иглы
- Используйте такие инструкции, которые быстрее
- Изменить путь выполненияподход так, чтобы все приложение использовало решение более эффективным способом
так что оно идет:
- strpos ($ haystack, $ what) - эту функцию можно удалить
- str_replace () можно заменить на in_array (), который должен быть быстрее.
- В вашем примере кода str_replace () должен искать букву, чтобы изменить всю длину $ haystack, умноженную на количество игл, так что если haystackимеет длину 10 символов, и у вас есть 5 игл, это означает, что str_replace выполняет поиск по общим 500 символам (5 раз поиск по 100 символьной строке).Если есть не 5, а 10 игл, а стог сена равен 1000 символов, то длина увеличивается до 10 тыс. В общем количестве символов для обработки str_replace.Вот почему вы видите резкое замедление выполнения при увеличении количества игл и / или длины стога сена.В идеале поиск должен быть выполнен один раз для всей длины стога сена, поэтому, если имеется 5 игл и стог сена равен 100 символам, поиск следует выполнять только один раз, и при этом нужно искать всего 100 символов, которые нужно искать.Дополнительно: для длинных строк, которые хранятся в файлах, вы можете вообще пропустить загрузку их в память, используя потоки и считывая их один за другим непосредственно из файла и заменяя их на лету.
код:
<?php
$needles = array('a', 'c', 'd');
$haystack = 'a b c d e f g';
function convert($needles, $haystack) {
if(is_resource($haystack)) {
$stream = $haystack;
} else {
$stream = fopen('data://text/plain,' . $haystack,'r');
}
while($char = fgetc($stream)) {
if(in_array($char, $needles)) {
$result = '#' . $char;
} else {
$result = $char;
}
yield $result;
}
if(is_resource($stream)) {
fclose($stream);
}
}
# use with haystack as string
$converted = convert($needles, $haystack);
# or use when haystack is in file
// $filePath = 'test-file.txt';
// $fileResource = fopen($filePath, 'r');
// $converted = convert($needles, $fileResource);
//echo converted string char by char
foreach($converted as $convertedChar) {
echo $convertedChar;
}
дает:
#a b #c #d e f g
как использовать:
поставить function convert() {}
определение везде, где вам нравится, и позже использовать его:
$needles = array('a', 'c', 'd');
$haystack = 'a b c d e f g';
$converted = convert($needles, $haystack);
$converted
теперь является своего рода массивом, каждый элемент которого представляет собой один символ преобразуемой строки.Таким образом, чтобы получить отображение всех символов, вы рассматриваете его как массив
['#a', 'b', '#c', '#d', 'e', 'f', 'g']
и эхо внутри цикла foreach:
//echo converted string char by char
foreach($converted as $convertedChar) {
echo $convertedChar;
}
хорошо то, что "видмассива "никогда не создается, он выглядит и выглядит как массив для foreach
, но на самом деле он возвращает только один символ, модифицированный итерацией foreach.Следовательно, потребление памяти функцией convert () почти ничем.
второй подход (объявление 3) - это прочитать весь стог сена из файла и обработать его на лету.Этот подход может обрабатывать даже очень большой стог сена, потому что он не считывает его в память сразу и сохраняет целое перед обработкой, но читает один символ из входных данных, а затем изменяет его и отображает эхо, а другой.
закомментируйте этот блокс кодом:
//$converted = convert($needles, $haystack);
и раскомментируйте это:
# or use when haystack is in file
$filePath = 'test-file.txt';
$fileResource = fopen($filePath, 'r');
$converted = convert($needles, $fileResource);
, затем выведите эхо, как прежде, с foreach
//echo converted string char by char
foreach($converted as $convertedChar) {
echo $convertedChar;
}
, если вы хотите сохранить преобразованный текст в строку, которую выможет сделать это так:
$convertedStr = '';
foreach($converted as $convertedChar) {
$convertedStr .= $convertedChar;
}
//and echo or save later
echo $convertedStr;