17

Функции startsWith() и endsWith() в PHP

18

Как я могу написать две функции, которые будет принимать строку и проверять, начинается ли она с указанного символа/строки или заканчивается на него?

Например:

$str = '|apples}';

echo startsWith($str, '|'); // Должно вернуть true
echo endsWith($str, '}'); // Должно вернуть true

5 ответ(ов)

1

Все ответы до сих пор кажутся чересчур затратными, с множеством ненужных вычислений strlen, выделений памяти под строки (например, с помощью substr) и т. д. Функции 'strpos' и 'stripos' возвращают индекс первого вхождения $needle в $haystack:

function startsWith($haystack, $needle, $case = true)
{
    if ($case)
        return strpos($haystack, $needle, 0) === 0;

    return stripos($haystack, $needle, 0) === 0;
}

function endsWith($haystack, $needle, $case = true)
{
    $expectedPosition = strlen($haystack) - strlen($needle);

    if ($case)
        return strrpos($haystack, $needle, 0) === $expectedPosition;

    return strripos($haystack, $needle, 0) === $expectedPosition;
}

Данный подход минимизирует лишние операции и делает код более эффективным. Функции просто проверяют, начинается ли строка с определённого подстроки или заканчивается на неё, без лишних затрат на выделение памяти или вычисление длинны строки там, где это не обязательно.

0

Этот вопрос уже имеет множество ответов, но в некоторых случаях можно обойтись чем-то более простым, чем все они.

Если строка, которую вы ищете, известна (зашита в коде), вы можете использовать регулярные выражения без каких-либо экранирований и т.п.

Проверка, начинается ли строка с 'ABC':

preg_match('/^ABC/', $myString); // "^" здесь означает начало строки

Проверка, заканчивается ли строка на 'ABC':

preg_match('/ABC$/', $myString); // "$" здесь означает конец строки

В моем простом случае я хотел проверить, заканчивается ли строка на слеш:

preg_match('#/$#', $myPath);   // Используйте "#" в качестве ограничителя вместо экранирования слэша

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

Но еще раз — это не решение для всех случаев, а только для очень конкретного.

0

Ваш код с регулярными выражениями работает правильно, чтобы проверить, начинается ли строка $haystack с подстроки $needle и заканчивается ли она на ту же подстроку. Ниже приведены исправленные функции с немного более полными комментариями:

function startsWith($needle, $haystack) {
    // Проверяем, начинается ли $haystack с $needle
    return preg_match('/^' . preg_quote($needle, '/') . '/', $haystack);
}

function endsWith($needle, $haystack) {
    // Проверяем, заканчивается ли $haystack на $needle
    return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);
}

Функции используют preg_match() с предобработанным шаблоном, созданным с помощью preg_quote(), который экранирует специальные символы в строке $needle. Это гарантирует, что в случае наличия специальных символов в подстроке, они не будут интерпретироваться как метасимволы регулярного выражения.

Таким образом, обе функции корректно проверяют соответствие для начала и конца строк. Если есть другие пожелания по улучшению или оптимизации, дайте знать!

0

Самое быстрое решение для endsWith():

# Проверяет, заканчивается ли строка на другую строку
function endsWith($haystack, $needle) {
    return substr($haystack, -strlen($needle) ) === $needle;
}

Бенчмарк:

# Это решение
function endsWith($haystack, $needle) {
    return substr($haystack, -strlen($needle) ) === $needle;
}

# Принятое решение
function endsWith2($haystack, $needle) {
    $length = strlen($needle);
    
    return $length === 0 ||
    (substr($haystack, -$length) === $needle);
}

# Второй по голосам ответ
function endsWith3($haystack, $needle) {
    // ищем начиная с конца, минус длина needle
    if ($needle === '') {
        return true;
    }
    $diff = \strlen($haystack) - \strlen($needle);
    return $diff >= 0 && strpos($haystack, $needle, $diff) !== false;
}

# Ответ с использованием регулярных выражений
function endsWith4($haystack, $needle) {
    return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);
}

function timedebug() {
    $test = 10000000;

    $time1 = microtime(true);
    for ($i = 0; $i < $test; $i++) {
        $tmp = endsWith('TestShortcode', 'Shortcode');
    }
    $time2 = microtime(true);
    $result1 = $time2 - $time1;

    for ($i = 0; $i < $test; $i++) {
        $tmp = endsWith2('TestShortcode', 'Shortcode');
    }
    $time3 = microtime(true);
    $result2 = $time3 - $time2;

    for ($i = 0; $i < $test; $i++) {
        $tmp = endsWith3('TestShortcode', 'Shortcode');
    }
    $time4 = microtime(true);
    $result3 = $time4 - $time3;

    for ($i = 0; $i < $test; $i++) {
        $tmp = endsWith4('TestShortcode', 'Shortcode');
    }
    $time5 = microtime(true);
    $result4 = $time5 - $time4;

    echo $test . 'x endsWith: ' . $result1 . ' seconds # Это решение<br>';
    echo $test . 'x endsWith2: ' . $result4 . ' seconds # Принятое решение<br>';
    echo $test . 'x endsWith3: ' . $result2 . ' seconds # Второй по голосам ответ<br>';
    echo $test . 'x endsWith4: ' . $result3 . ' seconds # Ответ с регулярными выражениями<br>';
    exit;
}
timedebug();

Результаты бенчмарка:

10000000x endsWith: 1.5760900974274 seconds # Это решение
10000000x endsWith2: 3.7102129459381 seconds # Принятое решение
10000000x endsWith3: 1.8731069564819 seconds # Второй по голосам ответ
10000000x endsWith4: 2.1521229743958 seconds # Ответ с регулярными выражениями

Если вам нужно наиболее производительное решение для проверки, заканчивается ли строка на другую строку, данное решение endsWith показывает лучшие результаты по сравнению с остальными вариантами.

0

Если скорость для вас важна, попробуйте это. (Я считаю, что это самый быстрый метод)

Данный подход работает только для строк и если $haystack состоит лишь из одного символа:

function startsWithChar($needle, $haystack)
{
   return ($needle === $haystack[0]);
}

function endsWithChar($needle, $haystack)
{
   return ($needle === $haystack[strlen($haystack) - 1]);
}

$str='|apples}';
echo startsWithChar('|',$str); // Возвращает true
echo endsWithChar('}',$str); // Возвращает true
echo startsWithChar('=',$str); // Возвращает false
echo endsWithChar('#',$str); // Возвращает false

Эти функции проверяют, начинается ли строка с заданного символа и заканчивается ли она на заданный символ соответственно.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь