Как я могу написать две функции, которые будут принимать строку и возвращаться, если она начинается с указанного символа / строки или заканчивается им?
Например:
$str = '|apples}'; echo startsWith($str, '|'); //Returns true echo endsWith($str, '}'); //Returns true
function startsWith($haystack, $needle) { $length = strlen($needle); return (substr($haystack, 0, $length) === $needle); } function endsWith($haystack, $needle) { $length = strlen($needle); return $length === 0 || (substr($haystack, -$length) === $needle); }
Используйте это, если вы не хотите использовать регулярное выражение.
Можно использовать strrpos
и strpos
для проверки начала и конца, соответственно.
Обратите внимание, что использование strrpos
для проверки начинается с и strpos
для проверки концов с возвратом как можно скорее, а не проверкой всей строки до конца. Кроме того, это решение не создает временную строку. Подумайте, объясните причину, предшествующую downvoting. Просто потому, что f-wit в DWTF не понимает, как работает эта функция или думает, что есть только одно решение, это не значит, что этот ответ неверен.
function startsWith($haystack, $needle) { // search backwards starting from haystack length characters from the end return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false; } function endsWith($haystack, $needle) { // search forward starting from end minus needle length characters return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== false); }
Тесты и результаты ( сравните с этим ):
startsWith("abcdef", "ab") -> true startsWith("abcdef", "cd") -> false startsWith("abcdef", "ef") -> false startsWith("abcdef", "") -> true startsWith("", "abcdef") -> false endsWith("abcdef", "ab") -> false endsWith("abcdef", "cd") -> false endsWith("abcdef", "ef") -> true endsWith("abcdef", "") -> true endsWith("", "abcdef") -> false
Примечание: функции strncmp
и substr_compare
будут превосходить эту функцию.
Обновлено 23 августа 2016 года
function substr_startswith($haystack, $needle) { return substr($haystack, 0, strlen($needle)) === $needle; } function preg_match_startswith($haystack, $needle) { return preg_match('~' . preg_quote($needle, '~') . '~A', $haystack) > 0; } function substr_compare_startswith($haystack, $needle) { return substr_compare($haystack, $needle, 0, strlen($needle)) === 0; } function strpos_startswith($haystack, $needle) { return strpos($haystack, $needle) === 0; } function strncmp_startswith($haystack, $needle) { return strncmp($haystack, $needle, strlen($needle)) === 0; } function strncmp_startswith2($haystack, $needle) { return $haystack[0] === $needle[0] ? strncmp($haystack, $needle, strlen($needle)) === 0 : false; }
echo 'generating tests'; for($i = 0; $i < 100000; ++$i) { if($i % 2500 === 0) echo '.'; $test_cases[] = [ random_bytes(random_int(1, 7000)), random_bytes(random_int(1, 3000)), ]; } echo "done!\n"; $functions = ['substr_startswith', 'preg_match_startswith', 'substr_compare_startswith', 'strpos_startswith', 'strncmp_startswith', 'strncmp_startswith2']; $results = []; foreach($functions as $func) { $start = microtime(true); foreach($test_cases as $tc) { $func(...$tc); } $results[$func] = (microtime(true) - $start) * 1000; } asort($results); foreach($results as $func => $time) { echo "$func: " . number_format($time, 1) . " ms\n"; }
(Отсортировано быстрее всего медленнее)
strncmp_startswith2: 40.2 ms strncmp_startswith: 42.9 ms substr_compare_startswith: 44.5 ms substr_startswith: 48.4 ms strpos_startswith: 138.7 ms preg_match_startswith: 13,152.4 ms
(Отсортировано быстрее всего медленнее)
strncmp_startswith2: 477.9 ms strpos_startswith: 522.1 ms strncmp_startswith: 617.1 ms substr_compare_startswith: 706.7 ms substr_startswith: 756.8 ms preg_match_startswith: 10,200.0 ms
startswith_benchmark.php
Все ответы до сих пор, похоже, выполняют множество ненужных работ, strlen calculations
, string allocations (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; }
function startsWith($haystack, $needle, $case = true) { if ($case) { return (strcmp(substr($haystack, 0, strlen($needle)), $needle) === 0); } return (strcasecmp(substr($haystack, 0, strlen($needle)), $needle) === 0); } function endsWith($haystack, $needle, $case = true) { if ($case) { return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0); } return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0); }
Кредит :
Проверьте, заканчивается ли строка другой строкой
Проверьте, начинается ли строка с другой строки
Регулярное выражение действует выше, но с другими настройками, также предложенными выше:
function startsWith($needle, $haystack) { return preg_match('/^' . preg_quote($needle, '/') . '/', $haystack); } function endsWith($needle, $haystack) { return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack); }
Если скорость важна для вас, попробуйте это. (Я считаю, что это самый быстрый метод)
Работает только для строк, а если $ haystack – только 1 символ
function startsWithChar($needle, $haystack) { return ($needle[0] === $haystack); } function endsWithChar($needle, $haystack) { return ($needle[strlen($needle) - 1] === $haystack); } $str='|apples}'; echo startsWithChar($str,'|'); //Returns true echo endsWithChar($str,'}'); //Returns true echo startsWithChar($str,'='); //Returns false echo endsWithChar($str,'#'); //Returns false
Я понимаю, что это было закончено, но вы можете посмотреть на strncmp, поскольку он позволяет вам сопоставить длину строки, поэтому:
function startsWith($haystack, $needle, $case=true) { if ($case) return strncasecmp($haystack, $needle, strlen($needle)) == 0; else return strncmp($haystack, $needle, strlen($needle)) == 0; }
Вот две функции, которые не вводят временную строку, которая может быть полезна, когда иглы существенно большие:
function startsWith($haystack, $needle) { return strncmp($haystack, $needle, strlen($needle)) === 0; } function endsWith($haystack, $needle) { return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0; }
На этот вопрос уже много ответов, но в некоторых случаях вы можете решить что-то более простое, чем все. Если строка, которую вы ищете, известна (жестко запрограммирована), вы можете использовать регулярные выражения без кавычек и т. Д.
Проверьте, начинается ли строка с «ABC»:
preg_match('/^ABC/', $myString); // "^" here means beginning of string
заканчивается на «ABC»:
preg_match('/ABC$/', $myString); // "$" here means end of string
В моем простом случае я хотел проверить, заканчивается ли строка косой чертой:
preg_match('/\/$/', $myPath); // slash has to be quoted
Преимущество: поскольку он очень короткий и простой, вам не нужно определять функцию (например, endsWith()
), как показано выше.
Но опять же – это не решение для каждого случая, просто для этого конкретного.
Вы можете использовать strpos
и strrpos
$bStartsWith = strpos($sHaystack, $sNeedle) == 0; $bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);
Короткие и легко понятные однострочники без регулярных выражений.
startsWith () – прямолинейный.
function startsWith($haystack, $needle) { return (strpos($haystack, $needle) === 0); }
endsWith () использует слегка причудливые и медленные strrev ():
function endsWith($haystack, $needle) { return (strpos(strrev($haystack), strrev($needle)) === 0); }
Сосредоточив внимание на startswith, если вы уверены, что строки не пустые, добавив тест на первый символ, перед сравнением, strlen и т. Д. Немного ускоряет работу:
function startswith5b($haystack, $needle) { return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE; }
Это как-то (на 20% -30%) быстрее. Добавление другого теста char, например $ haystack {1} === $ needle {1}, похоже, не ускоряет работу, может даже замедлить работу.
===
кажется быстрее, чем ==
Условный оператор (a)?b:c
выглядит быстрее, чем if(a) b; else c;
if(a) b; else c;
Для тех, кто спрашивает «почему бы не использовать strpos?» называя другие решения «ненужной работой»
strpos работает быстро, но это не правильный инструмент для этой работы.
Чтобы понять, вот немного моделирования в качестве примера:
Search a12345678c inside bcdefga12345678xbbbbb.....bbbbba12345678c
Что компьютер делает «внутри»?
With strccmp, etc... is a===b? NO return false With strpos is a===b? NO -- iterating in haysack is a===c? NO is a===d? NO .... is a===g? NO is a===g? NO is a===a? YES is 1===1? YES -- iterating in needle is 2===3? YES is 4===4? YES .... is 8===8? YES is c===x? NO: oh God, is a===1? NO -- iterating in haysack again is a===2? NO is a===3? NO is a===4? NO .... is a===x? NO is a===b? NO is a===b? NO is a===b? NO is a===b? NO is a===b? NO is a===b? NO is a===b? NO ... ... may many times... ... is a===b? NO is a===a? YES -- iterating in needle again is 1===1? YES is 2===3? YES is 4===4? YES is 8===8? YES is c===c? YES YES YES I have found the same string! yay! was it at position 0? NOPE What you mean NO? So the string I found is useless? YEs. Damn. return false
Предполагая, что strlen не выполняет итерацию всей строки (но даже в этом случае), это совсем не удобно.
Я надеюсь, что приведенный ниже ответ может быть эффективным и простым:
$content = "The main string to search"; $search = "T"; //For compare the begining string with case insensitive. if(stripos($content, $search) === 0) echo 'Yes'; else echo 'No'; //For compare the begining string with case sensitive. if(strpos($content, $search) === 0) echo 'Yes'; else echo 'No'; //For compare the ending string with case insensitive. if(stripos(strrev($content), strrev($search)) === 0) echo 'Yes'; else echo 'No'; //For compare the ending string with case sensitive. if(strpos(strrev($content), strrev($search)) === 0) echo 'Yes'; else echo 'No';
Обычно я в конечном итоге собираюсь с библиотекой, такой как underscore-php .
require_once("vendor/autoload.php"); //use if needed use Underscore\Types\String; $str = "there is a string"; echo( String::startsWith($str, 'the') ); // 1 echo( String::endsWith($str, 'ring')); // 1
Библиотека полна других удобных функций.
Функция substr
может возвращать false
во многих особых случаях, поэтому вот моя версия, которая касается этих проблем:
function startsWith( $haystack, $needle ){ return $needle === ''.substr( $haystack, 0, strlen( $needle )); // substr's false => empty string } function endsWith( $haystack, $needle ){ $len = strlen( $needle ); return $needle === ''.substr( $haystack, -$len, $len ); // ! len=0 }
Тесты ( true
означает хорошее):
var_dump( startsWith('','')); var_dump( startsWith('1','')); var_dump(!startsWith('','1')); var_dump( startsWith('1','1')); var_dump( startsWith('1234','12')); var_dump(!startsWith('1234','34')); var_dump(!startsWith('12','1234')); var_dump(!startsWith('34','1234')); var_dump('---'); var_dump( endsWith('','')); var_dump( endsWith('1','')); var_dump(!endsWith('','1')); var_dump( endsWith('1','1')); var_dump(!endsWith('1234','12')); var_dump( endsWith('1234','34')); var_dump(!endsWith('12','1234')); var_dump(!endsWith('34','1234'));
Кроме того, substr_compare
также стоит посмотреть. http://www.php.net/manual/en/function.substr-compare.php
вкратце:
function startsWith($str, $needle){ return substr($str, 0, strlen($needle)) === $needle; } function endsWith($str, $needle){ $length = strlen($needle); return !$length || substr($str, - $length) === $needle; }
Ответ mpen невероятно тщательный, но, к сожалению, предоставленный эталонный тест имеет очень важный и пагубный надзор.
Поскольку каждый байт в иголках и стогах сена является полностью случайным, вероятность того, что пара с иголовыми сенами будет отличаться на самом первом байте, составляет 99.609375%, а это значит, что в среднем около 99609 из 100000 пар будут отличаться на самом первом байте , Другими словами, эталонный показатель в значительной степени предвзято для startswith
реализациями, которые явно проверяют первый байт, как strncmp_startswith2
делает strncmp_startswith2
.
Если вместо этого выполняется тестовый цикл генерации, выполните следующие действия:
echo 'generating tests'; for($i = 0; $i < 100000; ++$i) { if($i % 2500 === 0) echo '.'; $haystack_length = random_int(1, 7000); $haystack = random_bytes($haystack_length); $needle_length = random_int(1, 3000); $overlap_length = min(random_int(0, $needle_length), $haystack_length); $needle = ($needle_length > $overlap_length) ? substr($haystack, 0, $overlap_length) . random_bytes($needle_length - $overlap_length) : substr($haystack, 0, $needle_length); $test_cases[] = [$haystack, $needle]; } echo " done!<br />";
результаты тестов показывают немного другую историю:
strncmp_startswith: 223.0 ms substr_startswith: 228.0 ms substr_compare_startswith: 238.0 ms strncmp_startswith2: 253.0 ms strpos_startswith: 349.0 ms preg_match_startswith: 20,828.7 ms
Конечно, этот тест все еще не может быть абсолютно беспристрастным, но он проверяет эффективность алгоритмов при одновременном использовании игольчатых игл.
Это может сработать
function startsWith($haystack, $needle) { return substr($haystack, 0, strlen($needle)) == $needle; }
Источник: https://stackoverflow.com/a/4419658
Почему бы не следующее?
//How to check if a string begins with another string $haystack = "valuehaystack"; $needle = "value"; if (strpos($haystack, $needle) === 0){ echo "Found " . $needle . " at the beginning of " . $haystack . "!"; }
Вывод:
Найдено значение в начале valuehaystack!
Имейте в виду, strpos
вернет false, если игла не была найдена в стоге сена, и вернет 0, если и только если игла была найдена с индексом 0 (AKA начало).
И вот концы с:
$haystack = "valuehaystack"; $needle = "haystack"; //If index of the needle plus the length of the needle is the same length as the entire haystack. if (strpos($haystack, $needle) + strlen($needle) === strlen($haystack)){ echo "Found " . $needle . " at the end of " . $haystack . "!"; }
В этом случае нет необходимости в функции startsWith () как
(strpos($stringToSearch, $doesItStartWithThis) === 0)
вернет true или false точно.
Кажется странным, что это просто, когда все дикие функции работают безудержными.
Я бы сделал это так
function startWith($haystack,$needle){ if(substr($haystack,0, strlen($needle))===$needle) return true; } function endWith($haystack,$needle){ if(substr($haystack, -strlen($needle))===$needle) return true; }
Основываясь на ответе Джеймса Блэка, вот его концы с версией:
function startsWith($haystack, $needle, $case=true) { if ($case) return strncmp($haystack, $needle, strlen($needle)) == 0; else return strncasecmp($haystack, $needle, strlen($needle)) == 0; } function endsWith($haystack, $needle, $case=true) { return startsWith(strrev($haystack),strrev($needle),$case); }
Примечание. Я заменил часть if-else для функции запуска JamesWhite, поскольку strncasecmp – это фактически не зависящая от регистра версия strncmp.
Просто рекомендация:
function startsWith($haystack,$needle) { if(!$needle) return true; if($haystack[0]<>$needle[0]) return false; if(substr_compare($haystack,$needle,0,strlen($needle))==0) return true; return false; }
Эта дополнительная строка, сравнивая первый символ строк, может немедленно вернуть ложный случай, поэтому значительно ускорить многие из ваших сравнений (на 7 раз быстрее, когда я измерял). В истинном случае вы не платите практически никакой цены за производительность для этой отдельной линии, поэтому я думаю, что это стоит того. (Кроме того, на практике, когда вы тестируете множество строк для определенного начального фрагмента, большинство сравнений не сработают, поскольку в типичном случае вы что-то ищете).
$ends_with = strrchr($text, '.'); // Ends with dot $start_with = (0 === strpos($text, '.')); // Starts with dot
Вот многобайтная безопасная версия принятого ответа, она отлично работает для строк UTF-8:
function startsWith($haystack, $needle) { $length = mb_substr($needle, 'UTF-8'); return (mb_substr($haystack, 0, $length, 'UTF-8') === $needle); } function endsWith($haystack, $needle) { $length = mb_strlen($needle, 'UTF-8'); return $length === 0 || (mb_substr($haystack, -$length, $length, 'UTF-8') === $needle); }
Вы также можете использовать регулярные выражения:
function endsWith($haystack, $needle, $case=true) { return preg_match("/.*{$needle}$/" . (($case) ? "" : "i"), $haystack); }
Многие из предыдущих ответов будут работать так же хорошо. Однако это возможно так коротко, как вы можете это сделать, и делать то, что вам нужно. Вы просто заявляете, что хотите, чтобы он вернул true. Поэтому я включил решения, которые возвращают логическое значение true / false и текстовое значение true / false.
// boolean true/false function startsWith($haystack, $needle) { return strpos($haystack, $needle) === 0 ? 1 : 0; } function endsWith($haystack, $needle) { return stripos($haystack, $needle) === 0 ? 1 : 0; } // textual true/false function startsWith($haystack, $needle) { return strpos($haystack, $needle) === 0 ? 'true' : 'false'; } function endsWith($haystack, $needle) { return stripos($haystack, $needle) === 0 ? 'true' : 'false'; }
Вот эффективное решение для PHP 4. Вы можете получить более быстрые результаты, если на PHP 5 с помощью substr_compare
вместо strcasecmp(substr(...))
.
function stringBeginsWith($haystack, $beginning, $caseInsensitivity = false) { if ($caseInsensitivity) return strncasecmp($haystack, $beginning, strlen($beginning)) === 0; else return strncmp($haystack, $beginning, strlen($beginning)) === 0; } function stringEndsWith($haystack, $ending, $caseInsensitivity = false) { if ($caseInsensitivity) return strcasecmp(substr($haystack, strlen($haystack) - strlen($ending)), $haystack) === 0; else return strpos($haystack, $ending, strlen($haystack) - strlen($ending)) !== false; }
Не знаю, почему это так сложно для людей. Substr выполняет отличную работу и эффективен, так как вам не нужно искать всю строку, если она не соответствует.
Additionally, since I'm not checking integer values but comparing strings I don't have to necessarily have to worry about the strict === case. However, === is a good habit to get into.
function startsWith($haystack,$needle) { substring($haystack,0,strlen($needle)) == $needle) { return true; } return false; } function endsWith($haystack,$needle) { if(substring($haystack,-strlen($needle)) == $needle) { return true; } return false; }
or even better optimized.
function startsWith($haystack,$needle) { return substring($haystack,0,strlen($needle)) == $needle); } function endsWith($haystack,$needle) { return substring($haystack,-strlen($needle)) == $needle); }