PHP स्ट्रिंग किसी अन्य स्ट्रिंग के साथ समाप्त होती है या नहीं, इसका सबसे कुशल परीक्षण क्या है?


125

एक स्ट्रिंग स्ट्रिंग के $strसाथ समाप्त होती है या नहीं यह जांचने के लिए मानक PHP तरीका $testहै:

$endsWith = substr( $str, -strlen( $test ) ) == $test

क्या यह सबसे तेज़ तरीका है?



जैसा कि इस स्वसंपूर्ण पुस्तकालय में पाया गया है, आप इसे उपयोगी s($str)->endsWith($test)या s($str)->endsWithIgnoreCase($test)उपयोगी मान सकते हैं
caw

जवाबों:


152

असफ ने जो कहा वह सही है। वहाँ वास्तव में ऐसा करने के लिए PHP में एक समारोह में बनाया गया है।

substr_compare($str, $test, strlen($str)-strlen($test), strlen($test)) === 0;

यदि PHP $testसे अधिक है तो $strएक चेतावनी देगा, इसलिए आपको पहले उस की जांच करनी होगी।

function endswith($string, $test) {
    $strlen = strlen($string);
    $testlen = strlen($test);
    if ($testlen > $strlen) return false;
    return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
}

अच्छा लगा। ऐसा लगता है कि इन-प्लेस की तुलना पदार्थ () से तेज होगी, जैसा कि आसफ ने कहा है।
जेसन कोहेन

2
mcrumley का उत्तर ठंडा है, लेकिन इसे '==' के बजाय '===' का उपयोग करना चाहिए। '===' अधिक सख्त है और आमतौर पर वही होता है जो आप चाहते हैं, जबकि '==' बुरा आश्चर्य पैदा कर सकता है। mcrumley का तीसरा कोड स्निपेट सही है, लेकिन पहले दो नहीं हैं। कुछ त्रुटि मामलों में root_compare () गलत है। PHP में, गलत == 0, इसलिए कोड स्निपेट संकेत देगा कि स्ट्रिंग पाया गया है। === के साथ, ऐसा नहीं होता है।
jcsahnwaldt

1
मैं आज एक बग में भाग गया जो PHP 5.5.11 और उसके बाद दिए गए समाधान को तोड़ देगा। Bugs.php.net/bug.php?id=67043
user2180613

3 फ़ंक्शन कॉल ओवरहेड इसे सबसे तेज़ नहीं बनाता है।
थान ट्रुंग

66

यह विधि थोड़ी अधिक स्मृति-महंगी है, लेकिन यह अधिक तेज़ है:

stripos(strrev($haystack), $reversed_needle) === 0;

यह सबसे अच्छा है जब आप जानते हैं कि सुई क्या है, इसलिए आप इसे उलट कर सकते हैं। यदि आप सुई को प्रोग्रामिक रूप से उलटते हैं, तो यह पहले की विधि की तुलना में धीमी हो जाती है।


2
-1 मुझे गंभीरता से संदेह है कि यह तेज है, और यह मुश्किल है (शांत लेकिन आमतौर पर मददगार नहीं है)। यदि सुई के साथ हैस्टैक समाप्त नहीं होता है , striposतो सबसे खराब स्थिति में पूरे स्ट्रिंग को पुनरावृत्त substr_compareकरेगा जबकि सुई की अधिकांश लंबाई पर तुलना करेगा। हां, substr_compareहिस्टैक की लंबाई (और बहुत छोटी सुई) की गणना करने की आवश्यकता होती है, लेकिन इस विधि की आवश्यकता होती है और इसे पूरी तरह से कॉपी करना, और संभवतः पूरी चीज को लोअरकेस में बूट करना।
डेविड हार्कस

कई मामलों में शांत दृष्टिकोण लेकिन अक्षम (जैसा कि उत्तर में ही उल्लेख किया गया है)! फिर भी अजीब तरह से रचनात्मक होने और यह प्रदर्शित करने के लिए एक उत्थान है कि हमेशा एक ही काम करने के अधिक तरीके हो सकते हैं जो आप कभी सोच सकते हैं। चीयर्स!
Fr0zenFyr

1
मैंने परीक्षण किया और स्वीकार किए गए उत्तर की तुलना में इस पद्धति को तेजी से पाया। यहां तक ​​कि अगर मक्खी पर सुई और सुई दोनों उलट दिए जाते हैं, तो यह तेज होता है।
शुमप्पा

@DavidHarkness क्या आपने यह देखने के लिए परीक्षण किया था कि क्या आपकी शंकाओं का समाधान किया गया था?
नाथन

@ नथन नहीं, यह substr_compare()अच्छी तरह से काम करने के बाद से बेंचमार्क करने के लिए समय के लायक नहीं है ।
डेविड हार्कस

61
$endsWith = substr_compare( $str, $test, -strlen( $test ) ) === 0

नकारात्मक ऑफसेट "स्ट्रिंग के अंत से गिनती शुरू होती है"।


3
IMO प्रदान किए गए समाधानों में से एक सबसे अच्छा है
रोमन पोडलिनोव

+200 अगर मैं कर सका। यहां मुख्य अंतर्दृष्टि यह है कि एक नकारात्मक लंबाई का उपयोग करने से स्ट्रिंग का अंत भाग मिलता है। आप -ve लंबाई के साथ भी रूट का उपयोग कर सकते हैं और $ परीक्षण के खिलाफ == कर सकते हैं। अन्य उत्तर खराब हैं।
निक

11

यहां यह जांचने का एक सरल तरीका है कि क्या एक स्ट्रिंग दूसरे के साथ समाप्त होती है, strposएक ऑफसेट अधिकार देकर जहां स्ट्रिंग मिलनी चाहिए:

function stringEndsWith($whole, $end)
{
    return (strpos($whole, $end, strlen($whole) - strlen($end)) !== false);
}

सीधा, और मुझे लगता है कि यह PHP 4 में काम करेगा।


8

यह निर्भर करता है कि आप किस प्रकार की दक्षता के बारे में परवाह करते हैं।

रूट के उपयोग से अतिरिक्त प्रतिलिपि के कारण आपका संस्करण अधिक मेमोरी का उपयोग करता है।

एक वैकल्पिक संस्करण एक प्रतिलिपि बनाने के बिना सबस्ट्रिंग की अंतिम घटना के लिए मूल स्ट्रिंग खोज सकता है, लेकिन अधिक परीक्षण के कारण शायद धीमा होगा।

संभवतः सबसे कुशल तरीका स्ट्रिंग के अंत तक -sterlen (परीक्षण) स्थिति से लूप चार-बाय-चार करना है और तुलना करें। यह तुलना करने की न्यूनतम मात्रा है जिसे आप करने की उम्मीद कर सकते हैं और शायद ही कोई अतिरिक्त मेमोरी का उपयोग किया गया हो।


5

एक और तरीका यह होगा कि आप strrposफंक्शन का इस्तेमाल करें :

strrpos($str, $test) == strlen($str) - strlen($test)

लेकिन यह तेज नहीं है।


3

मुझे उम्मीद है कि नीचे उत्तर कुशल और सरल भी हो सकता है:

$content = "The main string to search";
$search = "search";
//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';

2

पता नहीं कि यह तेज़ है या नहीं, लेकिन एक ही चरित्र परीक्षण के लिए, ये काम भी:

(array_pop(str_split($string)) === $test) ? true : false;
($string[strlen($string)-1] === $test) ? true : false;
(strrev($string)[0] === $test) ? true : false;

1

नियमित अभिव्यक्ति के माध्यम से इसे जांचने का सबसे आसान तरीका

उदाहरण के लिए जाँच करें कि क्या मेल दिया गया है जीमेल:

echo (preg_match("/@gmail\.com$/","example-email@gmail.com"))?'true':'false';

0

मैं सोच रहा हूं कि स्ट्रैचर () जैसे रिवर्स फंक्शन आपको स्ट्रिंग के अंत को सबसे तेजी से मैच करने में मदद करेंगे।


0

यह शुद्ध PHP है, बाहरी कार्यों को कॉल किए बिना, स्ट्रेलन को छोड़कर ।

function endsWith ($ends, $string)
{
    $strLength = strlen ($string);
    $endsLength = strlen ($ends);
    for ($i = 0; $i < $endsLength; $i++)
    {
        if ($string [$strLength - $i - 1] !== $ends [$i])
            return false;
    }
    return true;
}

0

एकल-चार सुई के लिए:

if (@strrev($haystack)[0] == $needle) {
   // yes, it ends...
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.