Soru Başka bir dizgiden “StartsWith” dizgisi nasıl kontrol edilir?


C # 'lerin eşdeğerini nasıl yazarım String.StartsWith JavaScript’te

var haystack = 'hello world';
var needle = 'he';

//haystack.startsWith(needle) == true

Not: Bu eski bir sorudur ve ECMAScript 2015 (ES6) tarafından sunulan yorumlarda belirtildiği gibi .startsWith yöntem. Ancak, bu güncellemenin yazıldığı sırada (2015) tarayıcı desteği tamamlanmış olmaktan uzak.


1547
2018-03-14 20:12


Menşei




Cevaplar:


ECMAScript 6'ları kullanabilirsiniz String.prototype.startsWith() yöntem, ama henüz tüm tarayıcılarda desteklenmiyor. Onu desteklemeyen tarayıcılara eklemek için bir shim / polyfill kullanmak istersiniz. İle uyumlu bir uygulama oluşturma spekülasyonda yer alan tüm detaylar biraz karmaşık ve bu cevapta tanımlanan sürüm bunu yapmayacak; sadık bir şim istiyorsanız, aşağıdakilerden birini kullanın:

Yöntemi değiştirdikten sonra (ya da zaten var olan tarayıcıları ve JavaScript motorlarını destekliyorsanız), bunu şu şekilde kullanabilirsiniz:

"Hello World!".startsWith("He"); // true

var haystack = "Hello world";
var prefix = 'orl';
haystack.startsWith(prefix); // false

1655
2018-03-14 20:19



Yerel ile JSPerf startsWith: jsperf.com/js-startwith-prototype/8 - JimmyBoh
@gtournie neden bir dizge bir dizeyle başlayıp başlamadığını test etmenin en kötü yöntemlerinden biri olacak mı? (burada yorumunuza bakın: stackoverflow.com/questions/646628/...) Karakter başına karakter karşılaştırmak konusunda daha hevesli. derler, her dizge [indeks] için bir dize oluşturmak için yeterince akıllı olmadıklarını çünkü eğer şunu yazarsanız: karakter = string [0] bir obje tahsis eder, infazitly beginWith kullanmaktan daha az verimli (startWith herhangi bir bellek ayırmaz ) - Martijn Scheffer
@MartijnScheffer: Cevap verdiğimden bu yana birçok kez düzenlenmiş ve şimdi tamamen farklı (yorumumu kaldırdım;). ECMAScript 6'ların start yönteminin bunu yapmanın en iyi yolu olduğuna katılıyorum. - gtournie
@GrahamLaight, 'IE' tarafından desteklendiğini söylediğinizde, muhtemelen Edge tarafından kastedilmektedir. developer.mozilla.org/en/docs/Web/JavaScript/Reference/... - Marcus
@Marcus, yanılıyor olsaydım özür dilerim - bilgilerim geldi: w3schools.com/jsref/jsref_startswith.asp - Graham Laight


İle başka bir alternatif .lastIndexOf:

haystack.lastIndexOf(needle, 0) === 0

Bu geriye doğru görünüyor haystack bir oluşumu için needle dizinden başlayarak 0 arasında haystack. Diğer bir deyişle, sadece kontrol eder haystack ile başlar needle.

Prensip olarak, bu diğer bazı yaklaşımlara göre performans avantajlarına sahip olmalıdır:

  • Tümünde arama yapmıyor haystack.
  • Yeni bir geçici dize oluşturmaz ve hemen atılır.

1226
2018-01-02 16:14



@ Rfcoder89'un hangi durumda olduğuna emin değil - jsfiddle.net/jkzjw3w2/1 - Gulfaraz Yasin
@ rfcoder89 lastIndexOf'in ikinci parametresine dikkat edin: "aba".lastIndexOf ("a") işaret ettiğin gibi 2, ama "aba".lastIndexOf ("a", 0) 0, hangisi doğru - maxpolk
Çok teşekkür ederim. String.startsWith Android lolipop WebView üzerinde çalışmıyor, ancak bu lastIndexOf parçacığı yok! - Herman
ile lastIndexOf dize, sondan baştan sonuna kadar aranır, böylece tüm dizeyi arar: bu yüzden verimsizliği aramak için çok uzun dizeler için büyür. - willy wonka
@willywonka Hayır, 0 startIndex'iniz yok, 0'dan arandı ve tek onay. Tüm dize yalnızca fromIndex> = str.length ise aranır. - greene


data.substring(0, input.length) === input

569
2018-03-14 20:14



@ANeves Şüphelendiğim tarayıcıya ve kullanılan verilere bağlı. Gerçek ölçümler için Ben Weaver'ın cevabını görün. Şu anda çalışmakta olduğum tarayıcıda (Chrome 12.0.742, Windows) altyazı, başarı için hazırlandı ve başarısızlık için hazırlanmış normal ifade kazanır. - cobbal
@cobbal Belki. Fakat .lastIndexOf(input, 0) ilk N karakterini karşılaştırır. .substring(0, input.length) === input N sayıyor, verileri N uzunluğuna dizer ve sonra bu N karakterlerini karşılaştırır. Kod optimizasyonu olmadığı sürece, bu ikinci sürüm diğerinden daha hızlı olamaz. Beni yanlış anlamayın, asla kendime önerdiğinden daha iyi bir şey bulamazdım. :) - ANeves
@ANeves Ancak .lastIndexOf, false döndürecek olan uzun bir dizgede tüm dizgenin (O (N)) üzerinde yineleme yaparken, .substring durumu potansiyel olarak çok daha küçük bir dizede yinelenir. Eğer çoğunluk başarıları veya sadece küçük girdiler bekliyorsanız, .lastIndexOf muhtemelen daha hızlıdır - aksi takdirde .substring daha hızlıdır. .substring ayrıca giriş kontrol edilen dizeden daha uzunsa bir istisna da risk oluşturur. - Chris Moschini
@ChrisMoschini, Mark Byers'ın çözümünün olduğunu unutma. lastIndexOf endeksi 0 değil, son değil. Bu da beni başlangıçta tetikledi. Yine de, bir dizenin neyle başladığını kontrol etmek, JavaScript'in bu sayfa için gördüğünüz tüm deyimler ve alternatifleri değil, bunun için uygun bir API'ye sahip olması gereken çok yaygın bir görevdir. - Randall Cook
Mark'ın üzerinde kobbal çözümünü tercih ederim. İşaretler daha hızlı olsa ve parazitleri kullanan etkileyici bir numara olsa bile, alt dizeyle karşılaştırıldığında okunması çok zordur. - ThinkBonobo


Bir yardımcı işlevi olmadan, sadece regex'in .test yöntem:

/^He/.test('Hello world')

Bunu kodlanmış bir kod yerine dinamik bir dizeyle yapmak için (dizenin herhangi bir regexp denetim karakteri içermediğini varsayarak):

new RegExp('^' + needle).test(haystack)

Kontrol etmelisiniz Javascript'te RegExp.escape işlevi var mı? regexp denetim karakterlerinin dizede görünme olasılığı varsa.


180
2018-01-04 00:59





Sadece bu konuda fikrimi eklemek istedim.

Sanırım şu şekilde kullanabiliriz:

var haystack = 'hello world';
var needle = 'he';

if (haystack.indexOf(needle) == 0) {
  // Code if string starts with this substring
}

50
2018-02-12 14:47



Mark Byers yanıtı, @relfor tarafından üç farklı doğru yaklaşımın performansı için karşılaştırıldı. Bu doğru yaklaşım, tüm dizinin aranmasını gerektirdiği için tercih edilmedi. - maxpolk
@maxpolk bence indexOf ilk varlığı bulduğunda tüm dizgeyi aramayı durdurur. Kontrol ettim. - Mr.D
Eğer ilk oluşum en başlarda bulunmazsa, bu yaklaşım, daha uzun süre vazgeçmek yerine, aramaya devam edene kadar potansiyel olarak arama yapmaya devam ederse, verimsiz olmaya başlar. Verimsizlik potansiyeli olduğundan, üç doğru yaklaşım arasında tercih edilmemektedir. - maxpolk
@ Mr.D Ve eşleşme yoksa? - momo
@momomo Sonra ekle else kodu. - Mr.D


En iyi çözüm:

function startsWith(str, word) {
    return str.lastIndexOf(word, 0) === 0;
}

startsWith("aaa", "a")
true
startsWith("aaa", "ab")
false
startsWith("abc", "abc")
true
startsWith("abc", "c")
false
startsWith("abc", "a")
true
startsWith("abc", "ba")
false
startsWith("abc", "ab")
true

Ve işte endswith eğer buna da ihtiyacınız varsa:

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

Onu dize prototiplemeyi tercih edenler için: 

String.prototype.startsWith || (String.prototype.startsWith = function(word) {
    return this.lastIndexOf(word, 0) === 0;
});

String.prototype.endsWith   || (String.prototype.endsWith = function(word) {
    return this.indexOf(word, this.length - word.length) !== -1;
});

Kullanımı: 

"abc".startsWith("ab")
true
"c".ensdWith("c") 
true

42
2018-04-26 21:56



Sanırım, fonksiyonlarınızda lastIndexOf ve indexOf'leri karıştırdınız - başlarsa, geri dönmelisiniz str.indexOf (word, 0) === 0; - Richard Matheson
@RichardMathes, indexOf kullanarak sorunu çözerse, başlangıçta eşleşme başarısız olursa, tüm dizgeyi aramaya devam edecektir, burada lastIndexOf sözcüğün uzunluğundan başlar ve sıfıra geri döner. Anladım? - momo
Ahh evet şimdi mantıklı - kullandığınız indekslere dikkat etmedim. Çok güzel numara! - Richard Matheson


İşte CMS'nin çözümüne küçük bir gelişme:

if(!String.prototype.startsWith){
    String.prototype.startsWith = function (str) {
        return !this.indexOf(str);
    }
}

"Hello World!".startsWith("He"); // true

 var data = "Hello world";
 var input = 'He';
 data.startsWith(input); // true

Gelecekteki bir tarayıcının bunu yerel kodda uyguladığı veya başka bir kitaplık tarafından uygulandığı durumda zaten var olan işlevin kontrol edilip edilmediğini kontrol etme. Örneğin, Prototip Kitaplığı zaten bu işlevi uygular.

kullanma ! biraz daha hızlı ve daha özlü === 0 okunabilir değil.


37
2018-05-27 02:54



Bu bir sorun olabilir: Eğer zaten uygulanmış olan uygulama kendi başıma farklı davranıyorsa, bu benim başvurumu kırdı. - Christoph Wurm
Burada tartışılan O (N) sorunu var. stackoverflow.com/questions/646628/javascript-startswith/... - Chris Moschini
kullanarak! çok dağınık - Jonny Leeds
1; bunu ekleyerek String.prototype Kötü bir fikir çünkü her şeye uymaya yakın bir yere gelmiyor spec için String.prototype.startsWith. ES6 yöntemini kullanmaya çalışan herhangi bir kod, bunu yapıyorsanız başarısız olabilir; Yöntemin önceden tanımlanmış olup olmadığına bakabilir, bunun (kötü bir şekilde sizin tarafınızdan) olduğunu görebilir ve daha sonra yanlış davranışa yol açacak şekilde özel bir şemayı eklemeyebilirsiniz. - Mark Amery
Bu iyi değil. - momo


Ayrıca check out underscore.string.js. Dahil bir dizi kullanışlı dizi testi ve manipülasyon yöntemleri ile birlikte gelir. startsWith yöntem. Dokümanlardan:

ile başlar  _.startsWith(string, starts)

Bu yöntem olup olmadığını kontrol eder. string ile başlar starts.

_("image.gif").startsWith("image")
=> true

21
2018-05-31 18:29



ihtiyacım vardı _.string.startsWith - Colonel Panic


Son zamanlarda kendime aynı soruyu sordum.
Birden fazla olası çözüm var, burada 3 geçerli olanı:

  • s.indexOf(starter) === 0
  • s.substr(0,starter.length) === starter
  • s.lastIndexOf(starter, 0) === 0 (Mark Byers'ın gördükten sonra eklendi Cevap)
  • bir döngü kullanarak:

    function startsWith(s,starter) {
      for (var i = 0,cur_c; i < starter.length; i++) {
        cur_c = starter[i];
        if (s[i] !== starter[i]) {
          return false;
        }
      }
      return true;
    }
    

Bir döngüden yararlanan son çözümle karşılaşmadım.
Şaşırtıcı bir şekilde bu çözüm ilk 3'ü önemli bir marjla geride bırakıyor.
İşte bu sonuca ulaşmak için yaptığım jsperf testi: http://jsperf.com/startswith2/2

Barış

ps: ecmascript 6 (uyum) bir yerel tanıtıyor startsWith dizeleri için yöntem.
İlk versiyonun kendisinde bu çok ihtiyaç duyulan yöntemi dahil etmeyi düşünürsek ne kadar zamanın saklanacağını düşünün.

Güncelleştirme

Steve'in işaret ettiği gibi (bu cevaba ilişkin ilk yorum), yukarıdaki özel işlev, verilen bir hatayı atar. önek tüm dizeden daha kısadır. Bunu düzeltdi ve görüntülenebilir bir döngü optimizasyonu ekledi http://jsperf.com/startswith2/4.

Steve'in dahil ettiği 2 döngü optimizasyonu olduğunu, ikisinden birincisinin daha iyi bir performans gösterdiğini, dolayısıyla bu kodu aşağıya yayınlayacağımı unutmayın:

function startsWith2(str, prefix) {
  if (str.length < prefix.length)
    return false;
  for (var i = prefix.length - 1; (i >= 0) && (str[i] === prefix[i]); --i)
    continue;
  return i < 0;
}

15
2018-05-17 09:07



En son rev. Yukarıdaki sürümdeki hatanın yanı sıra (dizenin önekden daha kısa olması durumunda atılacaktır), daha da optimize edilmiş bir sürümden daha yavaştır. Görmek jsperf.com/startswith2/4 ve jsperf.com/js-startswith/35. - Steve Hollasch
^ Dizenin önekten daha kısa olduğu durumu işaretlediğiniz için teşekkürler - Raj Nathani
jsperf.com/startswith2/29 => beginWith5 özlü ve gerçekten iyi performans gösteriyor =) - gtournie