tutorial - php এর কাজ কি




শুরু() এবং শেষ(পিএইচপি ফাংশন সহ) (20)

আমি কীভাবে দুটি ফাংশন লিখতে পারি যা একটি স্ট্রিং নেবে এবং যদি এটি নির্দিষ্ট অক্ষর / স্ট্রিং দিয়ে শুরু হয় বা এটির সাথে শেষ হয়?

উদাহরণ স্বরূপ:

$str = '|apples}';

echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true

Fastest endsWith() solution:

# Checks if a string ends in a string
function endsWith($haystack, $needle) {
    return substr($haystack,-strlen($needle))===$needle;
}

Benchmark:

# This answer
function endsWith($haystack, $needle) {
    return substr($haystack,-strlen($needle))===$needle;
}

# Accepted answer
function endsWith2($haystack, $needle) {
    $length = strlen($needle);

    return $length === 0 ||
    (substr($haystack, -$length) === $needle);
}

# Second most-voted answer
function endsWith3($haystack, $needle) {
    // search forward starting from end minus needle length characters
    if ($needle === '') {
        return true;
    }
    $diff = \strlen($haystack) - \strlen($needle);
    return $diff >= 0 && strpos($haystack, $needle, $diff) !== false;
}

# Regex answer
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 # This answer<br>';
    echo $test.'x endsWith2: '.$result4.' seconds # Accepted answer<br>';
    echo $test.'x endsWith3: '.$result2.' seconds # Second most voted answer<br>';
    echo $test.'x endsWith4: '.$result3.' seconds # Regex answer<br>';
    exit;
}
timedebug();

Benchmark Results:

10000000x endsWith: 1.5760900974274 seconds # This answer
10000000x endsWith2: 3.7102129459381 seconds # Accepted answer
10000000x endsWith3: 1.8731069564819 seconds # Second most voted answer
10000000x endsWith4: 2.1521229743958 seconds # Regex answer

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";
}

ফলাফল (পিএইচপি 7.0.9)

(সর্বাধিক ধীরতম অনুসারে সাজানো)

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

ফলাফল (পিএইচপি 5.3.29)

(সর্বাধিক ধীরতম অনুসারে সাজানো)

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


আপনি strrpos এবং strrpos ব্যবহার করতে পারেন

$bStartsWith = strpos($sHaystack, $sNeedle) == 0;
$bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);

আমি বুঝতে পেরেছি এটি শেষ হয়ে গেছে, কিন্তু আপনি strncmp এ দেখতে চাইতে পারেন কারণ এটি আপনাকে স্ট্রিংয়ের দৈর্ঘ্যকে তুলনা করার অনুমতি দেয়, তাই:

function startsWith($haystack, $needle, $case=true) {
    if ($case)
        return strncasecmp($haystack, $needle, strlen($needle)) == 0;
    else
        return strncmp($haystack, $needle, strlen($needle)) == 0;
}    

এই প্রশ্নটিতে ইতিমধ্যে অনেকগুলি উত্তর আছে, কিন্তু কিছু ক্ষেত্রে আপনি তাদের সব চেয়ে সহজ কিছু স্থির করতে পারেন। আপনি যে স্ট্রিংটি সন্ধান করছেন তা যদি পরিচিত হয় (হার্ডকোডেড), আপনি কোন উদ্ধৃতি ছাড়াই নিয়মিত এক্সপ্রেশন ব্যবহার করতে পারেন।

একটি স্ট্রিং 'ABC' দিয়ে শুরু হয় কিনা তা পরীক্ষা করুন:

preg_match('/^ABC/', $myString); // "^" here means beginning of string

'এবিসি' দিয়ে শেষ হয়:

preg_match('/ABC$/', $myString); // "$" here means end of string

আমার সহজ ক্ষেত্রে, আমি একটি স্ট্রিং স্ল্যাশ সঙ্গে শেষ কিনা তা পরীক্ষা করতে চেয়েছিলেন:

preg_match('#/$#', $myPath);   // Use "#" as delimiter instead of escaping slash

সুবিধা: এটি খুব ছোট এবং সরল কারণ, উপরে endsWith() হিসাবে আপনি একটি ফাংশন সংজ্ঞায়িত করতে হবে না (যেমন শেষ endsWith()

কিন্তু আবার - এই প্রতিটি ক্ষেত্রে একটি সমাধান, শুধু এই খুব নির্দিষ্ট এক।


এখানে গৃহীত উত্তরটির একটি মাল্টি-বাইট নিরাপদ সংস্করণ রয়েছে, এটি 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);
}

গতি আপনার জন্য গুরুত্বপূর্ণ হলে, চেষ্টা করুন। (আমি এটা দ্রুততম পদ্ধতি বিশ্বাস করি)

শুধুমাত্র স্ট্রিংগুলির জন্য কাজ করে এবং $ 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

দ্বারা answer অবিশ্বাস্যভাবে পুঙ্খানুপুঙ্খ, কিন্তু, দুর্ভাগ্যবশত, প্রদত্ত বেঞ্চমার্ক একটি খুব গুরুত্বপূর্ণ এবং ক্ষতিকর তত্ত্বাবধান আছে।

সূঁচ এবং হায়স্ট্যাক্সের প্রত্যেকটি বাইট সম্পূর্ণরূপে র্যান্ডম, কারণ প্রথম বাইটে সুই-হায়স্ট্যাক জোড়াটি পৃথক হবে বলে সম্ভাব্যতা 99.609375%, যা গড়ত, 100000 জোড়াগুলির 99609 জোড়া প্রথম বাইটে ভিন্ন হবে । অন্য কথায়, বেঞ্চমার্কটি startswith বাস্তবায়নগুলির দিকে তীব্রভাবে পক্ষপাতী, যা প্রথম বাইটটি স্পষ্টভাবে পরীক্ষা করে, যেমন 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 startswith5b($haystack, $needle) {
    return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;
}

এটা কোনোভাবে (20% -30%) দ্রুত। $ গৃহস্থালি {1} === $ সুই {1} মত আরেকটি গৃহস্থালি পরীক্ষা যুক্ত করা খুব দ্রুত গতিশীল বলে মনে হচ্ছে না, এমনকি ধীর হতে পারে।

=== == শর্তাধীন অপারেটর (a)?b:c চেয়ে দ্রুত মনে হয় (a)?b:c if(a) b; else c; চেয়ে দ্রুত মনে হয় if(a) b; else c; if(a) b; else c;

যারা জিজ্ঞাসা করে "কেন স্ট্রপ ব্যবহার করবেন না?" অন্যান্য সমাধান কলিং "অপ্রয়োজনীয় কাজ"

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 assuming পুরো স্ট্রিং পুনরাবৃত্তি না (কিন্তু যে ক্ষেত্রে এমনকি) এই সব সুবিধাজনক নয়।


সমস্ত উত্তর পর্যন্ত অপ্রয়োজনীয় কাজের লোড, string allocations (substr) strlen calculations , string allocations (substr) ইত্যাদি কাজ করে বলে মনে হয়। 'stripos' এবং 'stripos' ফাংশন $needle 'stripos' এর $needle 'stripos' প্রথম ঘটনার সূচী ফিরিয়ে দেয়:

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;
}

Based on James Black's answer, here is its endsWith version:

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);

}

Note: I have swapped the if-else part for James Black's startsWith function, because strncasecmp is actually the case-insensitive version of strncmp.


Here's an efficient solution for PHP 4. You could get faster results if on PHP 5 by using substr_compare instead of 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;
}

I would do it like this

     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;
        }

Just a recommendation:

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;
}

That extra line, comparing the first character of the strings, can make the false case return immediately , therefore making many of your comparisons a lot faster (7x faster when I measured). In the true case you pay virtually no price in performance for that single line so I think it's worth including. (Also, in practice, when you test many strings for a specific starting chunk, most comparisons will fail since in a typical case you're looking for something.)


Not sure why this is so difficult for people. Substr does a great job and is efficient as you don't need to search the whole string if it doesn't match.

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);
}

The substr function can return false in many special cases, so here is my version, which deals with these issues:

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
}

Tests ( true means good):

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'));

Also, the substr_compare function also worth looking. http://www.php.net/manual/en/function.substr-compare.php


Why not the following?

//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 . "!";
}

Output:

Found value at the beginning of valuehaystack!

Keep in mind, strpos will return false if the needle was not found in the haystack, and will return 0 if, and only if, needle was found at index 0 (AKA the beginning).

And here's endsWith:

$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 . "!";
}

In this scenario there is no need for a function startsWith() as

(strpos($stringToSearch, $doesItStartWithThis) === 0)

will return true or false accurately.

It seems odd it's this simple with all the wild functions running rampant here.


You also can use regular expressions:

function endsWith($haystack, $needle, $case=true) {
  return preg_match("/.*{$needle}$/" . (($case) ? "" : "i"), $haystack);
}

function startsWith($haystack, $needle)
{
     $length = strlen($needle);
     return (substr($haystack, 0, $length) === $needle);
}

function endsWith($haystack, $needle)
{
    $length = strlen($needle);
    if ($length == 0) {
        return true;
    }

    return (substr($haystack, -$length) === $needle);
}

আপনি একটি regex ব্যবহার করতে চান না, তাহলে এই ব্যবহার করুন।


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);
}

ক্রেডিট :

একটি স্ট্রিং অন্য স্ট্রিং সঙ্গে শেষ কিনা তা পরীক্ষা করুন

একটি স্ট্রিং অন্য স্ট্রিং দিয়ে শুরু কিনা তা পরীক্ষা করুন





string