kończy się w JavaScript

1103

Jak mogę sprawdzić, czy ciąg znaków kończy się określonym znakiem w JavaScript?

Przykład: Mam ciąg

var str = "mystring#";

Chcę wiedzieć, czy ten ciąg się kończy #. Jak mogę to sprawdzić?

  1. Czy endsWith()w JavaScript jest metoda?

  2. Jednym z moich rozwiązań jest wzięcie długości łańcucha, pobranie ostatniego znaku i sprawdzenie go.

Czy to najlepszy sposób, czy jest jakiś inny sposób?

Bobby Kumar
źródło

Odpowiedzi:

1764

AKTUALIZACJA (24 listopada 2015):

Ta odpowiedź została pierwotnie opublikowana w roku 2010 (SZEŚĆ lat wstecz.), Więc zwróć uwagę na te wnikliwe komentarze:


ORYGINALNA ODPOWIEDŹ:

Wiem, że to jest pytanie sprzed lat ... ale ja też tego potrzebuję i potrzebuję go do pracy w różnych przeglądarkach, więc ... łącząc odpowiedzi i komentarze wszystkich i nieco upraszczając:

String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
  • Nie tworzy podciągu
  • Używa indexOffunkcji natywnej w celu uzyskania najszybszych wyników
  • Pomiń niepotrzebne porównania, używając drugiego parametru, indexOfaby przejść do przodu
  • Działa w Internet Explorerze
  • Bez powikłań Regex

Ponadto, jeśli nie lubisz upychać rzeczy w prototypach natywnej struktury danych, oto samodzielna wersja:

function endsWith(str, suffix) {
    return str.indexOf(suffix, str.length - suffix.length) !== -1;
}

EDYCJA: Jak zauważył @hamish w komentarzach, jeśli chcesz popełnić błąd po bezpiecznej stronie i sprawdzić, czy implementacja została już zapewniona, możesz po prostu dodać typeofkontrolę w ten sposób:

if (typeof String.prototype.endsWith !== 'function') {
    String.prototype.endsWith = function(suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}
czakryt
źródło
42
Aktualizacja dla pracowników Google - wygląda na to, że ECMA6 dodaje tę funkcję. Artykuł MDN pokazuje również wypełnienie. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Shauna
2
@ lukas.pukenis przeskakuje do końca i sprawdza tylko jedną instancję sufiksu na samym końcu. nie ma znaczenia, czy szukany ciąg pojawia się gdzie indziej.
chakrit
3
Dodanie kontroli sytuacji, gdy argument „sufiks” nie jest zdefiniowany ”: if (typeof String.prototype.endsWith! == 'function') {String.prototype.endsWith = function (sufiks) {return this.indexOf (sufiks , this.length - ((sufiks && sufiks.length) || 0))! == -1;};}
Mandeep
2
Jakie powikłania wyrażenia regularnego, o których mówiłeś?
IcedDante,
5
Tworzenie podciągów nie jest drogie w nowoczesnych przeglądarkach; być może w 2010 roku opublikowano tę odpowiedź. Obecnie proste this.substr(-suffix.length) === suffixpodejście jest najszybsze w Chrome, takie samo jak w IE11 indexOfi tylko o 4% wolniejsze (terytorium fergetaboutit) w Firefox: jsperf.com/endswith-stackoverflow/14 I szybsze we wszystkich przypadkach, gdy wynik jest fałszywy: jsperf .com / end-with-stackoverflow-when-false Oczywiście, z dodawaniem ES6 endsWith, chodzi o dyskusję. :-)
TJ Crowder
295
/#$/.test(str)

będzie działać na wszystkich przeglądarkach, nie wymaga łatania małp Stringi nie wymaga skanowania całego łańcucha, jak lastIndexOfma to miejsce w przypadku braku dopasowania.

Jeśli chcesz dopasować stały ciąg znaków, który może zawierać znaki specjalne wyrażeń regularnych, takie jak '$', możesz użyć następujących opcji:

function makeSuffixRegExp(suffix, caseInsensitive) {
  return new RegExp(
      String(suffix).replace(/[$%()*+.?\[\\\]{|}]/g, "\\$&") + "$",
      caseInsensitive ? "i" : "");
}

i wtedy możesz użyć tego w ten sposób

makeSuffixRegExp("a[complicated]*suffix*").test(str)
Mike Samuel
źródło
10
Jest to przyjemne i proste, jeśli sprawdzasz ciągły podciąg.
Warren Blanchet
1
lastIndexOf skanuje cały ciąg? Myślałem, że będzie szukać od końca do początku.
Tom Brito
3
@TomBrito, lastIndexOfskanuje cały ciąg tylko wtedy, gdy nie znajdzie dopasowania lub znajdzie dopasowanie na początku. Jeśli na końcu jest dopasowanie, to działa ono proporcjonalnie do długości sufiksu. Tak, /asdf$/.test(str)daje true, gdy strkończy się na "asdf".
Mike Samuel,
3
@Tom Brito, to dosłowne wyrażenie regularne. Składnia została zapożyczona z Perla. Zobacz developer.mozilla.org/en/Core_JavaScript_1.5_Guide/... lub niepotrzebny poziom szczegółowości, patrz sekcja 7.8.5 specyfikacji języka EcmaScript.
Mike Samuel,
2
+1 za kompatybilność z różnymi przeglądarkami. Testowane na Chrome 28.0.1500.72 m, Firefox 22.0 i IE9.
Adrien Be
91
  1. Niestety nie.
  2. if( "mystring#".substr(-1) === "#" ) {}
Phillip B Oldham
źródło
14
@Anthony, um ... więc użyj .Length-1, w czym problem? if (mystring.substr (mystring.length-1) === "#") {} działa dobrze w IE.
BrainSlugs83
12
@ BrainSlugs83 - to jest właśnie problem: składnia „.length-1” działa w IE, a składnia „-1” nie. Warto o tym pamiętać, więc +1 dla Anthony'ego za wskazówkę.
avramov
2
Nie mogłeś użyć slice()? Działa to w moim szybkim teście IE7.
alex
zakręcony IE. kiedy to umrze?
ahnbizcad
67

Chodź, to jest poprawna endsWithimplementacja:

String.prototype.endsWith = function (s) {
  return this.length >= s.length && this.substr(this.length - s.length) == s;
}

użycie lastIndexOftylko tworzy niepotrzebne pętle procesora, jeśli nie ma dopasowania.

Oskar Liljeblad
źródło
2
Zgoda. Naprawdę uważam, że jest to najbardziej wydajne rozwiązanie oferowane, ponieważ ma wczesne sprawdzanie przerwania / poczytalności, jest krótkie i zwięzłe, jest eleganckie (przeciążenie prototypu łańcucha), a podciąganie wydaje się być znacznie mniejszym hitem niż rozruszanie silnika regex.
BrainSlugs83
Również podoba mi się to rozwiązanie. Tylko nazwa funkcji jest błędna. Powinien być „kończy się na”.
xmedeko,
3
@ BrainSlugs83 Minęło kilka lat, ale teraz ta metoda nie jest szybsza niż metoda „indexOf” wspomniana powyżej przez chakrit, aw Safari jest o 30% wolniejsza! Oto test jsPerf dla przypadku niepowodzenia o długości około 50 znaków: jsperf.com/endswithcomparison
Brent Faust
4
Prawdopodobnie powinien ===jednak użyć .
Timmmm,
56

Ta wersja unika tworzenia podłańcucha i nie używa wyrażeń regularnych (niektóre odpowiedzi wyrażeń regularnych będą działać, inne są uszkodzone):

String.prototype.endsWith = function(str)
{
    var lastIndex = this.lastIndexOf(str);
    return (lastIndex !== -1) && (lastIndex + str.length === this.length);
}

Jeśli wydajność jest dla Ciebie ważna, warto sprawdzić, czy lastIndexOfrzeczywiście jest szybsza niż tworzenie podłańcucha, czy nie. (Może to zależeć od używanego silnika JS ...) Może być szybsze w dopasowanym przypadku, a gdy łańcuch jest mały - ale gdy łańcuch jest duży, musi spojrzeć wstecz przez całą rzecz, nawet chociaż tak naprawdę nas to nie obchodzi :(

charAtNajlepszym sposobem na sprawdzenie pojedynczego znaku jest znalezienie jego długości, a następnie użycie .

Jon Skeet
źródło
2
Jeśli this.lastIndexOf () zwraca -1, możesz trafić w przypadki, w których zwraca true w zależności od this.length i str.length. Dodaj test, który lastIndexOf ()! = -1.
ebruchez
1
Dlaczego metoda regex jest zepsuta?
izb
2
@izb: Odpowiedzi starsze niż moje, które próbują użyć str+"$"jako wyrażenia regularnego, są niepoprawne, ponieważ mogą nie być poprawnymi wyrażeniami regularnymi.
Jon Skeet
26

Nie widziałem slicemetody apporach . Więc zostawiam to tutaj:

function endsWith(str, suffix) {
    return str.slice(-suffix.length) === suffix
}
Nikita Koksharov
źródło
1
Możesz to nieco uprościć: return str.slice (-1) === przyrostek;
Erik K.,
2
To najlepsza odpowiedź. Nie jestem pewien, dlaczego nie ma więcej pozytywnych opinii.
nukleartyd
17
return this.lastIndexOf(str) + str.length == this.length;

nie działa w przypadku, gdy oryginalna długość ciągu jest o jeden mniejsza niż długość ciągu wyszukiwania i nie znaleziono ciągu wyszukiwania:

lastIndexOf zwraca -1, następnie dodajesz długość szukanego ciągu i pozostaje ci długość oryginalnego ciągu.

Możliwą poprawką jest

return this.length >= str.length && this.lastIndexOf(str) + str.length == this.length
użytkownik73745
źródło
30
Zdobyłeś odznakę „Znalazłem błąd w odpowiedzi Jona Skeeta”. Zobacz swój profil, aby uzyskać szczegółowe informacje.
bobince
17

From developer.mozilla.org String.prototype.endsWith ()

Podsumowanie

endsWith()Metoda określa, czy końce ciąg z bohaterów inny ciąg, powracającego prawda czy fałsz jako właściwe.

Składnia

str.endsWith(searchString [, position]);

Parametry

  • searchString : Znaki, które mają być wyszukiwane na końcu tego ciągu.

  • pozycja : Szukaj w tym ciągu tak, jakby ten ciąg był tylko tak długi; domyślnie jest to rzeczywista długość łańcucha, zaciśnięta w zakresie ustalonym przez długość łańcucha.

Opis

Ta metoda pozwala określić, czy łańcuch kończy się na innym łańcuchu.

Przykłady

var str = "To be, or not to be, that is the question.";

alert( str.endsWith("question.") );  // true
alert( str.endsWith("to be") );      // false
alert( str.endsWith("to be", 19) );  // true

Dane techniczne

ECMAScript Language Specification 6. wydanie (ECMA-262)

Kompatybilność z przeglądarkami

Kompatybilność z przeglądarkami

Aniket Kulkarni
źródło
10
if( ("mystring#").substr(-1,1) == '#' )

- Lub -

if( ("mystring#").match(/#$/) )
duckyflip
źródło
8
String.prototype.endsWith = function(str) 
{return (this.match(str+"$")==str)}

String.prototype.startsWith = function(str) 
{return (this.match("^"+str)==str)}

mam nadzieję, że to pomoże

var myStr =   Earth is a beautiful planet  ”;
var myStr2 = myStr.trim();  
//==“Earth is a beautiful planet”;

if (myStr2.startsWith(“Earth”)) // returns TRUE

if (myStr2.endsWith(“planet”)) // returns TRUE

if (myStr.startsWith(“Earth”)) 
// returns FALSE due to the leading spaces…

if (myStr.endsWith(“planet”)) 
// returns FALSE due to trailing spaces…

tradycyjny sposób

function strStartsWith(str, prefix) {
    return str.indexOf(prefix) === 0;
}

function strEndsWith(str, suffix) {
    return str.match(suffix+"$")==suffix;
}
Mohammed Rafeeq
źródło
Musisz uciec od ciągu znaków, aby uzyskać sekwencje specjalne
Juan Mendes,
1
Wyrażenia regularne są wolne nawet w szybkich językach. Po prostu sprawdź koniec łańcucha.
Daniel Nuriyev
8

Nie wiem o tobie, ale:

var s = "mystring#";
s.length >= 1 && s[s.length - 1] == '#'; // will do the thing!

Dlaczego wyrażenia regularne? Po co mieszać z prototypem? substr? No chodź...

Tici
źródło
bo czasem jest lepiej, gdy jest
MOKRO
8

Kolejna szybka alternatywa, która działała dla mnie jak urok, używając wyrażenia regularnego:

// Would be equivalent to:
// "Hello World!".endsWith("World!")
"Hello World!".match("World!$") != null
Winicjusz
źródło
7

Jeśli używasz lodash :

_.endsWith('abc', 'c'); // true

Jeśli nie używasz lodash, możesz pożyczyć od źródła .

Dheeraj Vepakomma
źródło
6

Właśnie dowiedziałem się o tej bibliotece ciągów:

http://stringjs.com/

Dołącz plik js, a następnie użyj Szmiennej w następujący sposób:

S('hi there').endsWith('hi there')

Można go również użyć w NodeJS, instalując go:

npm install string

Wymagając go jako Szmiennej:

var S = require('string');

Strona internetowa zawiera również linki do alternatywnych bibliotek ciągów, jeśli ta nie przypadnie Ci do gustu.

Ashley Davis
źródło
4
function strEndsWith(str,suffix) {
  var reguex= new RegExp(suffix+'$');

  if (str.match(reguex)!=null)
      return true;

  return false;
}
Tabish Usman
źródło
1
Lepiej wyjaśnij, dlaczego Twój kod rozwiązuje problem. Zobacz przewodnik Jak odpowiedzieć .
brasofilo
argument sufiksu powinien zostać przeskanowany w poszukiwaniu wyrażeń regularnych, które muszą być poprzedzone znakami ucieczki. użycie indexOf lub lastIndexOf wydaje się lepszą opcją.
vlad_tepesch
To nie zadziała, jeśli przyrostek zawiera którykolwiek z następujących znaków
:.
4

Tak wiele rzeczy na tak mały problem, po prostu użyj tego wyrażenia regularnego

var str = "mystring#";
var regex = /^.*#$/

if (regex.test(str)){
  //if it has a trailing '#'
}

LahiruBandara
źródło
4

Wiele lat minęło od tego pytania. Pozwól mi dodać ważną aktualizację dla użytkowników, którzy chcą skorzystać z najczęściej głosowanej odpowiedzi czakrytu.

Funkcje „EndWith” są już dodane do JavaScript jako część ECMAScript 6 (technologia eksperymentalna)

Zobacz to tutaj: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith

Dlatego zaleca się dodanie sprawdzania istnienia natywnej implementacji, jak wspomniano w odpowiedzi.

ScrapCode
źródło
2
function check(str)
{
    var lastIndex = str.lastIndexOf('/');
    return (lastIndex != -1) && (lastIndex  == (str.length - 1));
}
maniakalny
źródło
2

Sposobem na przyszły dowód i / lub zapobieganie zastąpieniu istniejącego prototypu byłoby sprawdzenie testowe, aby sprawdzić, czy został on już dodany do prototypu String. Oto moje zdanie na temat wysoko ocenianej wersji nieregexowej.

if (typeof String.endsWith !== 'function') {
    String.prototype.endsWith = function (suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}
Dan Doyon
źródło
Korzystanie if (!String.prototype.hasOwnProperty("endsWith"))jest najlepszym sposobem. Dzięki typeof„MooTools i niektóre inne biblioteki AJAX mogą cię zepsuć”, zgodnie z „Crockford on JavaScript - Level 7: ECMAScript 5: The New Parts”, o 15:50 min.
XP1
2

Akceptowana odpowiedź @ chakrit to solidny sposób na samodzielne zrobienie tego. Jeśli jednak szukasz rozwiązania w pakiecie, polecam zajrzeć na underscore.string , jak wskazał @mlunoe. Przy użyciu underscore.string kod będzie wyglądał następująco:

function endsWithHash(str) {
  return _.str.endsWith(str, '#');
}
rmehlinger
źródło
1

jeśli nie chcesz używać lasIndexOf lub substr, to dlaczego nie spojrzeć na ciąg znaków w jego naturalnym stanie (tj. tablicę)

String.prototype.endsWith = function(suffix) {
    if (this[this.length - 1] == suffix) return true;
    return false;
}

lub jako samodzielna funkcja

function strEndsWith(str,suffix) {
    if (str[str.length - 1] == suffix) return true;
    return false;
}
użytkownik511941
źródło
1
String.prototype.endWith = function (a) {
    var isExp = a.constructor.name === "RegExp",
    val = this;
    if (isExp === false) {
        a = escape(a);
        val = escape(val);
    } else
        a = a.toString().replace(/(^\/)|(\/$)/g, "");
    return eval("/" + a + "$/.test(val)");
}

// example
var str = "Hello";
alert(str.endWith("lo"));
alert(str.endWith(/l(o|a)/));
Ebubekir Dirican
źródło
1

Po wszystkich tych długich zestawieniach odpowiedzi ten fragment kodu był prosty i łatwy do zrozumienia!

function end(str, target) {
  return str.substr(-target.length) == target;
}
immazharkhan
źródło
1

To jest implementacja EndWith: String.prototype.endsWith = function (str) { return this.length >= str.length && this.substr(this.length - str.length) == str; }

Singh123
źródło
1

Jest to implementacja endsWith:

String.prototype.endsWith = function (str) {
  return (this.length >= str.length) && (this.substr(this.length - str.length) === str);
}
Singh123
źródło
0

Opiera się to na zaakceptowanej odpowiedzi @ charkit, która pozwala na przekazanie tablicy argumentów lub ciągu znaków jako argumentu.

if (typeof String.prototype.endsWith === 'undefined') {
    String.prototype.endsWith = function(suffix) {
        if (typeof suffix === 'String') {
            return this.indexOf(suffix, this.length - suffix.length) !== -1;
        }else if(suffix instanceof Array){
            return _.find(suffix, function(value){
                console.log(value, (this.indexOf(value, this.length - value.length) !== -1));
                return this.indexOf(value, this.length - value.length) !== -1;
            }, this);
        }
    };
}

Wymaga to podkreślenia - ale prawdopodobnie można je dostosować, aby usunąć zależność podkreślenia.

Matthew Brown
źródło
1
To złe rozwiązanie, a jeśli już używasz podkreślenia, dodaj ten epeli.github.io/underscore.string do swoich zależności i użyj ich implementacji:_.str.endsWith
mlunoe
0
if(typeof String.prototype.endsWith !== "function") {
    /**
     * String.prototype.endsWith
     * Check if given string locate at the end of current string
     * @param {string} substring substring to locate in the current string.
     * @param {number=} position end the endsWith check at that position
     * @return {boolean}
     *
     * @edition ECMA-262 6th Edition, 15.5.4.23
     */
    String.prototype.endsWith = function(substring, position) {
        substring = String(substring);

        var subLen = substring.length | 0;

        if( !subLen )return true;//Empty string

        var strLen = this.length;

        if( position === void 0 )position = strLen;
        else position = position | 0;

        if( position < 1 )return false;

        var fromIndex = (strLen < position ? strLen : position) - subLen;

        return (fromIndex >= 0 || subLen === -fromIndex)
            && (
                position === 0
                // if position not at the and of the string, we can optimise search substring
                //  by checking first symbol of substring exists in search position in current string
                || this.charCodeAt(fromIndex) === substring.charCodeAt(0)//fast false
            )
            && this.indexOf(substring, fromIndex) === fromIndex
        ;
    };
}

Korzyści:

  • Ta wersja nie tylko ponownie używa indexOf.
  • Najlepsza wydajność na długich strunach. Oto test prędkości http://jsperf.com/starts-ends-with/4
  • W pełni kompatybilny ze specyfikacją ecmascript. Przechodzi testy
termi
źródło
0

Nie używaj wyrażeń regularnych. Są powolne, nawet w szybkich językach. Po prostu napisz funkcję, która sprawdza koniec łańcucha. Ta biblioteka ma ładne przykłady: groundjs / util.js . Uważaj, dodając funkcję do String.prototype. Ten kod zawiera ładne przykłady, jak to zrobić: groundjs / prototype.js Ogólnie rzecz biorąc, jest to przyjemna biblioteka na poziomie językowym: groundjs Możesz także rzucić okiem na lodash

Daniel Nuriyev
źródło
0

wszystkie z nich są bardzo przydatnymi przykładami. Dodanie String.prototype.endsWith = function(str)pomoże nam po prostu wywołać metodę, aby sprawdzić, czy nasz łańcuch się z tym kończy, czy też nie, dobrze, też będzie to wyrażenie regularne.

Znalazłem lepsze rozwiązanie niż moje. Dziękuję wszystkim.

Bobby Kumar
źródło
0

Do coffeescript

String::endsWith = (suffix) ->
  -1 != @indexOf suffix, @length - suffix.length
Quanlong
źródło