Функция PHP, которая добавляет # хэштег к массиву слов - PullRequest
0 голосов
/ 01 июня 2019

Я пытаюсь написать функцию, которая добавляет знак # к массиву слов в строке

Учитывая, что я могу использовать str_replace для каждого из них, но мой массив становится больше и он неэффективен.

$needles = array('a', 'c', 'd');
$haystack = 'a b c d e f g';
    foreach($needles as $what) {
        if(strpos($haystack, $what)!==false) {
     $haystack = str_replace($needles, '#'.$what.'-', $haystack);
    }
    }
echo $haystack;

Массив здесь представляет собой иголки a c d в стоге сена a b c d e f g Я пытаюсь сделать их #a #b #c, чтобы результат был # a b #c #d e f g

Ответы [ 3 ]

1 голос
/ 01 июня 2019

Вы неправильно используете эту функцию str_replace () Подробнее об этой функции читайте здесь функция str_replace

$needles = array('a', 'c', 'd');
$haystack = 'a b c d e f g';

    foreach($needles as $key) {
        if(strpos($haystack, $key)!==false) {
     $haystack = str_replace($key, '#'.$key, $haystack);
    }
    }
echo $haystack;

Выход

#a b #c #d e f g

Надеюсь, это поможет вам

0 голосов
/ 01 июня 2019

Как это можно оптимизировать:

  1. Инструкции предельного количества, которые необходимо выполнить для каждой иглы
  2. Используйте такие инструкции, которые быстрее
  3. Изменить путь выполненияподход так, чтобы все приложение использовало решение более эффективным способом

так что оно идет:

  1. strpos ($ haystack, $ what) - эту функцию можно удалить
  2. str_replace () можно заменить на in_array (), который должен быть быстрее.
  3. В вашем примере кода 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;
0 голосов
/ 01 июня 2019

Я не уверен, что если это будет быстрее, вам придется его тестировать, но это решение работает. Regex медленный, но итерация по строке один раз должна быть быстрее, чем просмотр ее N раз.

<?php
$needles = array('a', 'c', 'd');
$haystack = 'a b c d e f g';
$reg = '~(['.implode($needles).'])~';

echo preg_replace ( $reg, '#$1' , $haystack );

Выход

#a b #c #d e f g
...