JavaScript'te dize eşleşmesi için anahtar deyimi


193

Aşağıdaki koşul için nasıl bir anahtar yazabilirim?

URL "foo" içeriyorsa , settings.base_url "bar" dır.

Aşağıdakiler gereken efekti elde ediyor, ancak bunun bir anahtarda daha yönetilebilir olacağını hissediyorum:

var doc_location = document.location.href;
var url_strip = new RegExp("http:\/\/.*\/");
var base_url = url_strip.exec(doc_location)
var base_url_string = base_url[0];

//BASE URL CASES

// LOCAL
if (base_url_string.indexOf('xxx.local') > -1) {
    settings = {
        "base_url" : "http://xxx.local/"
    };
}

// DEV
if (base_url_string.indexOf('xxx.dev.yyy.com') > -1) {
    settings = {
        "base_url" : "http://xxx.dev.yyy.com/xxx/"
    };
}

Yanıtlar:


352

Bir de bunu yapamaz switchyaptığınızı sürece tam dize eşleme; alt dize uyumu yapıyor . (Bu değil oldukça Sean yorumlarda işaret ettiği gibi, gerçek. Sonundaki nota bakın.)

En üstteki normal ifadenizin, maçınızda karşılaştırmak istemediğiniz her şeyi kaldırdığından memnunsanız, bir alt dize maçına ihtiyacınız yoktur ve şunları yapabilirsiniz:

switch (base_url_string) {
    case "xxx.local":
        // Blah
        break;
    case "xxx.dev.yyy.com":
        // Blah
        break;
}

... ama yine de, bu sadece eşleştirdiğiniz tam dizge ise işe yarar . base_url_stringÖrneğin, "yyy.xxx.local" olsaydı başarısız olurken, mevcut kodunuz "xxx.local" dalındaki kodla eşleşirdi.


Güncelleme : Tamam, teknik olarak yapabilirsiniz bir kullanmak switcheşleştirme alt dize için, ama çoğu durumda bunu tavsiye etmem. İşte nasıl ( canlı örnek ):

function test(str) {
    switch (true) {
      case /xyz/.test(str):
        display("• Matched 'xyz' test");
        break;
      case /test/.test(str):
        display("• Matched 'test' test");
        break;
      case /ing/.test(str):
        display("• Matched 'ing' test");
        break;
      default:
        display("• Didn't match any test");
        break;
    }
}

Bu, JavaScript switchifadelerinin çalışma biçimi nedeniyle, özellikle de iki önemli yönü vardır: Birincisi, vakaların kaynak metin sırasına göre dikkate alınması ve ikincisi, seçici ifadelerin (anahtar kelimeden sonraki bitler case) bu vaka olarak değerlendirilen ifadeler olmasıdır değerlendirilir (diğer dillerde olduğu gibi sabit değildir). Bu yüzden test ifademiz olduğu için true, casesonuçlanan ilk ifade kullanılan ifade trueolacaktır.


91
Eski olduğunu biliyorum, ama bu doğru değil - aslında yapabilirsinizswitch(true) { case /foo/.test(bar): ....
Sean Kinsey

23
Oh tanrım hayır! Switch ifadesinin böyle çalışması gerekmiyor. Bu sadece kırıldı, böyle şeyler yapmak yasadışı olmalı.
Pijusn

47
Hoohoo, çok lezzetli.
Aditya MP

41
Hepiniz sadece bakış açınızı genişletmeniz gerekiyor. Bu Ruby'deki norm, çirkin olmak yerine, truehepsini bir arada bırakıyorsunuz.
emkman

49
Bunu seviyorum ve itiraf etmekten utanmıyorum.
chrisf

65

RegExp, giriş dizgisinde sadece teknik olarak değil, aynı zamanda pratikte de matchyöntemle kullanılabilir.

Bunun çıktısı match()bir dizi olduğu için sonucun ilk dizi elemanını almamız gerekir. Eşleşme başarısız olduğunda işlev geri döner null. İstisna hatasından kaçınmak için ||, ilk dizi öğesine erişmeden önce koşullu operatörü ekleyeceğiz ve giriş dizesini içeren normal ifadelerin statik bir özelliği olaninput özelliğe karşı test edeceğiz .

str = 'XYZ test';
switch (str) {
  case (str.match(/^xyz/) || {}).input:
    console.log("Matched a string that starts with 'xyz'");
    break;
  case (str.match(/test/) || {}).input:
    console.log("Matched the 'test' substring");        
    break;
  default:
    console.log("Didn't match");
    break;
}

Başka bir yaklaşım String()yapıcıyı .*kullanarak sadece 1 eleman (yakalama grubu yok) olmalı ve tüm dize quanitifiers ( ) ile bir dizeye yakalanmalıdır . Bir arıza durumunda, nullnesne bir "null"dize haline gelecektir . Uygun değil.

str = 'haystack';
switch (str) {
  case String(str.match(/^hay.*/)):
    console.log("Matched a string that starts with 'hay'");
    break;
}

Neyse, daha zarif bir çözüm kullanmaktır /^find-this-in/.test(str)ile switch (true)basitçe bir boolean değer döndüren yöntem ve harf duyarlılığı olmadan arama yapmak daha kolaydır.


1
pribilinsiky: muhtemelen üçüncü çözümünüzün (test () kullanarak) anahtar (true) olmasını gerektirdiğini belirtmelisiniz.
bugün

35

Location.host özelliğini kullanmanız yeterlidir

switch (location.host) {
    case "xxx.local":
        settings = ...
        break;
    case "xxx.dev.yyy.com":
        settings = ...
        break;
}

1
Teşekkürler, +1, gerçekten yapmam gereken şey bu
Dr. Frankenstein

Switch deyimine ilettiğiniz değişken türüne dikkat etmeniz gerekir. Bu gerekir bir dize. Yapabileceğinden emin olmak için switch ("" + location.host).
ceving

16

Diğer bir seçenek, normal ifade eşleşmesi sonucununinput alanını kullanmaktır :

str = 'XYZ test';
switch (str) {
  case (str.match(/^xyz/) || {}).input:
    console.log("Matched a string that starts with 'xyz'");
    break;
  case (str.match(/test/) || {}).input:
    console.log("Matched the 'test' substring");        
    break;
  default:
    console.log("Didn't match");
    break;
}

güzel bir. Bu durumda, herhangi bir dizi özelliği test için de kullanılabilir, örneğin.length:
Steven Pribilinskiy

6
var token = 'spo';

switch(token){
    case ( (token.match(/spo/) )? token : undefined ) :
       console.log('MATCHED')    
    break;;
    default:
       console.log('NO MATCH')
    break;;
}


-> Eğer eşleşme yapılırsa üçlü ifade orijinal jetonu döndürür
----> Orijinal jeton büyük / küçük harf durumuna göre değerlendirilir

-> Eğer maç yapılmazsa, üçlü geri dönüşler undefined
----> Case, jetonu, jetonun tanımlanmadığı, undefined'e göre değerlendirir.

Üçlü test, örneğin sizin durumunuzda herhangi bir şey olabilir

( !!~ base_url_string.indexOf('xxx.dev.yyy.com') )? xxx.dev.yyy.com : undefined 

===========================================

(token.match(/spo/) )? token : undefined ) 

a, üçlü ifade.

Bu durumda test, token'da tutulan dizenin regex ifadesi / spo / (bu durumda değişmez dizge spo olan) ile eşleştiğini belirten token.match (/ spo /) 'dir.

İfade ve dize eşleşirse true ile sonuçlanır ve jeton döndürür (switch deyiminin üzerinde çalıştığı dize).

Açıkça belirteç === belirteç, böylece anahtar deyimi eşleşir ve vaka değerlendirilir

Katmanlar halinde bakarsanız ve anahtar testinin yalnızca test sonuçlarını görmesi için anahtar testinin anahtar ifadesini "ÖNCE" olarak değerlendirdiğini anlamak daha kolaydır.


Cevabınız kafa karıştırıcı. Örneği ve açıklamayı gözden geçirip geliştirebilir misiniz?
falsarella

@falsarella Anlamakta zorlandığınızı düşündüğüm kısmı anlattım. Daha basit bir örnek verebileceğimi sanmıyorum. Daha fazla sorunuz varsa veya zorluklarınızla ilgili daha spesifik olabilirseniz daha fazla yardımcı olabilirim.
James

Tamam, şimdi anladım. Kafam karıştı çünkü token.match(/spo/)eşleşeceği belliydi .
falsarella

3

Daha kolay olabilir. Böyle düşünmeye çalışın:

  • önce normal karakterler arasında bir dize yakala
  • bundan sonra "dava" bulmak

:

// 'www.dev.yyy.com'
// 'xxx.foo.pl'

var url = "xxx.foo.pl";

switch (url.match(/\..*.\./)[0]){
   case ".dev.yyy." :
          console.log("xxx.dev.yyy.com");break;

   case ".some.":
          console.log("xxx.foo.pl");break;
} //end switch

Upvoted. Ancak not:TypeError: url.match(...) is null
1111161171159459134

1

Çok geç olabilir ve hepsi, ama ben atama durumunda bunu sevdim :)

function extractParameters(args) {
    function getCase(arg, key) {
        return arg.match(new RegExp(`${key}=(.*)`)) || {};
    }

    args.forEach((arg) => {
        console.log("arg: " + arg);
        let match;
        switch (arg) {
            case (match = getCase(arg, "--user")).input:
            case (match = getCase(arg, "-u")).input:
                userName = match[1];
                break;

            case (match = getCase(arg, "--password")).input:
            case (match = getCase(arg, "-p")).input:
                password = match[1];
                break;

            case (match = getCase(arg, "--branch")).input:
            case (match = getCase(arg, "-b")).input:
                branch = match[1];
                break;
        }
    });
};

olayı daha ileriye taşıyabilir ve bir seçenek listesini iletebilir ve normal ifadeyi |


1
Ben de değişeceğini || {}için || [-1]veya tip güvenliği için benzer. Ayrıca, neden new RegExpsadece eğik çizgiler değil?
Sergey Krasilnikov

Gerçekten de onu geliştirmek için zaman ayırmadı .. çalıştığı anda ben sadece devam ..... Şimdi utanıyorum.
TacB0sS

Panik yapmayın, bu sadece nit-pick'imdi;) Aslında haklı olduğumdan bile emin değilim, yeni bir şey öğrenmeye çalıştım.
Sergey Krasilnikov

Hayır ... haklısın ... Kesinlikle doğrulayabileceğim ve güzelleştirebilirdim .. Tekrar bu koda ulaştığımda yapacağım .. Umarım yakında olur :)
TacB0sS
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.