Bir sayıyı ay adına dönüştüren anahtar durumu bloğu nasıl kısaltılır?


110

Bunu daha az satıra yazmanın bir yolu var, ancak yine de kolayca okunabilir mi?

var month = '';

switch(mm) {
    case '1':
        month = 'January';
        break;
    case '2':
        month = 'February';
        break;
    case '3':
        month = 'March';
        break;
    case '4':
        month = 'April';
        break;
    case '5':
        month = 'May';
        break;
    case '6':
        month = 'June';
        break;
    case '7':
        month = 'July';
        break;
    case '8':
        month = 'August';
        break;
    case '9':
        month = 'September';
        break;
    case '10':
        month = 'October';
        break;
    case '11':
        month = 'November';
        break;
    case '12':
        month = 'December';
        break;
}

7
IMHO vidriduch'un cevabı en uygun olanıdır. Muhtemelen kodunuzun Tarih manipülasyonu gerektiren tek parçası bu değildir (gösterdiğinizin kodlaması özellikle kolay olsa da). Mevcut, test edilmiş Tarih kitaplıklarını kullanmayı ciddi olarak düşünmelisiniz.
coredump

2
JavaScript bilmiyorum ama Python'un sözlüğü veya C ++ 'ın std :: map gibi bir hashmap'i yok mu?
Maskeli Adam

28
Bunun codereview.stackexchange.com için olması gerekmiyor mu?
Loko

2
Varsayılanı hesaba katmayarak kodun davranışını değiştiren pek çok cevap, tanımsız çıktıyla sonuçlanır, bu da orijinalin yaptığından farklıdır.
Pieter B

2
Bu yinelenen bir soru değil > :( bu tamamen farklı bir soru soruyor, cevap aynı olabilir.
Leon Gaban

Yanıtlar:


199

Bir dizi tanımlayın, ardından dizine göre alın.

var months = ['January', 'February', ...];

var month = months[mm - 1] || '';

23
bunun yerine ilk değer olarak mm - 1da ayarlayabilirsiniz undefined(dizin 0), böylece dizi endeksleri ay sayılarıyla eşleşir
Touffy

9
var month = month[(mm -1) % 12]
mpez0

77
@ mpez0 Muhtemelen kötü verileri saklamak yerine, birinin 15. ayı bulmayı başardığını bilmeyi tercih ederim
Izkata

21
@Touffy ben sopa ile olacağını düşünüyorum mm-1böylece, months.length==12.
Teepeemm

48
@Touffy Bunun bir zevk meselesi olmadığını, zekice kodlardan kaçınma meselesi olduğunu düşünüyorum . Kendinizi başkalarınınkini okuduğunuzu hayal edin [undefined, 'January', 'February', ...]- en iyisi ilk tepkiniz WTF ?! , bu genellikle iyiye işaret değildir ...
miraculixx

81

dizi kullanmamaya ne dersiniz :)

var objDate = new Date("10/11/2009"),
    locale = "en-us",
    month = objDate.toLocaleString(locale, { month: "long" });

console.log(month);

// or if you want the shorter date: (also possible to use "narrow" for "O"
console.log(objDate.toLocaleString(locale, { month: "short" }));

bu yanıta göre Tarihten ay adını al David Storey'den al


2
Söz konusu problem ifadesi göz önüne alındığında, cevabınız o problemi gerçekten çözmek değil, farklı bir bağlamda doğru olabilecek farklı bir çözümdür. Seçilen cevap hala en iyi ve en verimli olanıdır.
TechMaze

6
Sadece new Date("2009-11-10")biçimi (: Bu SPECIFIATION bakınız ayrıştırılması garanti edilmektedir ecma-international.org/publications/standards/Ecma-262.htm ). Tarayıcı seçerse diğer tarih biçimleri (cevabınızda bir tane de dahil) ayrıştırılabilir ve bu nedenle taşınabilir değildir.
jb.

58

Bunu dene:

var months = {'1': 'January', '2': 'February'}; //etc
var month = months[mm];

Bunu not et mm bir tamsayı veya bir dize olabilir ve hala çalışır.

Var olmayan anahtarların boş dizeyle sonuçlanmasını istiyorsanız ''(yerine undefined), şu satırı ekleyin:

month = (month == undefined) ? '' : month;

JSFiddle .


4
"Yılın aylarından" daha büyük veri kümelerinde bu muhtemelen daha verimli olacaktır.
DGM

3
Bu, etkin bir şekilde bir numaralandırmadır (yani onu değiştirilemez hale getirin), JavaScript'te Enums'evar months = Object.freeze({'1': 'January', '2': 'February'}); //etc Bakın mı?
Alexander

1
@Alexander Anahtar ve değerleri değiştirirseniz, evet, bir numaralandırmaya benzer.
Ama Ben Sarıcı Sınıfı Değilim

26

Bunun yerine bir dizi oluşturabilir ve ay adını arayabilirsiniz:

var months = ['January','February','March','April','May','June','July','August','September','October','November','December']


var month = months[mm-1] || '';

Kodun ardındaki mantık için @CupawnTae'nin cevabına bakın || ''


yerine 0 indeksi ile başından daha saklayabildin undefinedde 0 olduğu gibi var months = [ undefined, 'January','February','March', .....kullanacağınız Bu yollamonth = months[mm];
Grijesh Chauhan

@GrijeshChauhan: Lütfen 'akıllı' koddan kaçının. Bir sonraki kişinin ilk tepkisi wtf olacaktır. Bu sadece bir '-1' aydır. Bu durumda uzunluk 13 olacaktır, wtf ^ 2. programmers.stackexchange.com/questions/91854/…
RvdK

19

Dikkatli ol!

Alarm zillerini hemen tetiklemesi gereken şey ilk satırdır: var month = '';- bu değişken neden nullveya yerine boş bir dizeyle başlatılıyor?undefined ? Bu sadece bir alışkanlık ya da kopyalama / yapıştırma olabilir, ancak kesin olarak bilmiyorsanız, kodu yeniden düzenlerken onu göz ardı etmek güvenli değildir.

Bir ay adları dizisi kullanır ve kodunuzu var month = months[mm-1];kendinize göre değiştirirseniz davranışı değiştirirsiniz, çünkü artık aralık dışındaki sayılar veya sayısal olmayan değerler monthiçinundefined . Bunun sorun olmadığını biliyor olabilirsiniz, ancak bunun kötü olacağı birçok durum vardır.

Örneğin, diyelim ki sizin switchbir fonksiyonda monthToName(mm)ve birisi sizin fonksiyonunuzu şöyle çağırıyor:

var monthName = monthToName(mm);

if (monthName === '') {
  alert("Please enter a valid month.");
} else {
  submitMonth(monthName);
}

Şimdi, bir dizi kullanmaya ve geri dönmeye geçerseniz monthName[mm-1], çağıran kod artık amaçlandığı gibi çalışmayacak ve undefinedbir uyarı göstermesi gerektiğinde değerleri gönderecektir . Bunun iyi bir kod olduğunu söylemiyorum , ancak kodun nasıl kullanıldığını tam olarak bilmiyorsanız, varsayımlarda bulunamazsınız.

Ya da belki de orijinal başlatma oradaydı çünkü satırın ilerisindeki bazı kodlar bunun monthher zaman bir dize olacağını varsayarmonth.length - bu geçersiz aylar için bir istisna atılmasına neden olacak ve potansiyel olarak çağıran betiği tamamen öldürecektir.

Eğer varsa bunu bilmek metnin bütününü - örneğin hepsi kendi kod ve başka hiç kimse onu kullanacak, ve kendinizi gelecekte değişiklik ara uygun yapılmış unutmamak güven - davranışını değiştirmek için güvenli olabilir bunun gibi, ancak pek çok hata bu tür bir varsayımdan geliyor, gerçek hayatta savunma amaçlı programlama ve / veya davranışı kapsamlı bir şekilde belgelemekten çok daha iyi olursunuz.

Wasmoo'nun cevabı doğru anlıyor (DÜZENLEME: kabul edilen cevap da dahil olmak üzere bir dizi başka cevap da düzeltildi) - kullanabilirsiniz months[mm-1] || ''veya bir bakışta neler olduğunu daha açık hale getirmeyi tercih ederseniz, şuna benzer bir şey:

var months = ['January', 'February', ...];

var month;

if (mm >= 1 && m <= 12) {
  month = months[mm - 1];
} else {
  month = ''; // empty string when not a valid month
}

1
Henüz hiç kimse davranıştaki değişiklikten bahsetmedi, bu nedenle kodu yeniden faktörlendirirken bu dikkate alınmalıdır.
Mauro

Bu cevap yerinde. Diğer cevapların çoğu kodun davranışını ince bir şekilde değiştirir. Bu önemli olmayabilir veya hata bulmak o kadar sinir bozucu derecede zor olabilir.
Pieter B

Ah öyleyse bir var'ı başlatmak her zaman en iyisidir undefined? Tür dönüştürülürse bu performans tasarrufu sağlar mı?
Leon Gaban

2
@LeonGaban, performansla ilgili değil: orijinal soru değişkeni boş bir dizge olarak başlattı ve geçerli bir ay seçilmediyse bu durumda bıraktı, oysa buradaki diğer cevapların çoğu bu gerçeği görmezden geldi undefinedve girdi olmadığında geri dönerek davranışı değiştirdi t 1..12. Çok istisnai durumlar dışında , doğru davranış her seferinde performanstan üstündür.
CupawnTae

17

Tamlık için, mevcut cevapları tamamlamak istiyorum. Temel olarak, breakanahtar kelimeyi çıkarabilir ve doğrudan uygun bir değeri döndürebilirsiniz. Değer önceden hesaplanmış bir arama tablosunda saklanamıyorsa bu taktik kullanışlıdır.

function foo(mm) {
    switch(mm) {
        case '1':  return 'January';
        case '2':  return 'February';
        case '3':  return 'March';
        case '4':  return 'April';
        // [...]
        case '12': return 'December';
    }
    return '';
}

Bir kez daha, bir arama tablosu veya tarih işlevlerini kullanmak daha kısa ve özneldir daha iyidir .


16

Bunu bir dizi kullanarak yapabilirsiniz:

var months = ['January', 'February', 'March', 'April', 
              'May', 'June', 'July', 'August', 
              'September', 'October', 'November', 'December'];

var month = months[mm - 1] || '';

12

Burada yalnızca 1 değişken kullanan ve aralık dışında ''olduğunda varsayılan değeri uygulayan başka bir seçenek var mm.

var month = ['January', 'February', 'March',
             'April', 'May', 'June', 'July',
             'August', 'September', 'October',
             'November', 'December'
            ][mm-1] || '';

Menzil kontrolü ve bir istisna atmak da işe yarayabilir. Ve "Hata" veya "Tanımsız" döndürülmesi boş dizeye alternatif olabilir.
ChuckCottrill

9

Koşullu operatörler kullanarak bunu bir anahtar yerine bir ifade olarak yazabilirsiniz:

var month =
  mm == 1 ? 'January' :
  mm == 2 ? 'February' :
  mm == 3 ? 'March' :
  mm == 4 ? 'April' :
  mm == 5 ? 'May' :
  mm == 6 ? 'June' :
  mm == 7 ? 'July' :
  mm == 8 ? 'August' :
  mm == 9 ? 'September' :
  mm == 10 ? 'October' :
  mm == 11 ? 'November' :
  mm == 12 ? 'December' :
  '';

Daha önce zincirleme koşullu işleçler görmediyseniz, bunu ilk başta okumak daha zor görünebilir. Bunu bir ifade olarak yazmak, bir yönün orijinal koddan daha kolay görülmesini sağlar; Kodun amacının değişkene bir değer atamak olduğu açıktır month.


1
Bunu da önermek istedim. Özlü kalırken aslında çok okunabilir ve dizi çözümünün yapamadığı seyrek eşlemeler ve sayısal olmayan anahtarlar için iyi sonuç verir. Not: Cevabımda da rastgele açıklanamayan bir olumsuz oy aldım - muhtemelen aynı arabadan geçen sanatçı.
CupawnTae

6

Bina Cupawn Tae en cevabı önceki I o kadar kısaltmak istiyorum:

var months = ['January', 'February', ...];
var month = (mm >= 1 && mm <= 12) ? months[mm - 1] : '';

Alternatif olarak, evet, takdir ediyorum, daha az okunaklı:

var month = months[mm - 1] || ''; // as mentioned further up

Atlayabilir (!!months[mm - 1])ve basitçe yapabilirsiniz months[mm - 1].
YingYang

Dizi dizini aralık dışında olsaydı bu tanımsız olarak sonuçlanırdı!
NeilElliott-NSDev

months[mm - 1]undefinedaralık dışı bir dizin için dönecektir . Yana undefinedfalsy size ile sona erecek ''değeri olarak month.
YingYang

Diğer cevaplarda da belirtildiği gibi bu satırı daha da basitleştirebilirsiniz:var month = months[mm - 1] || '';
YingYang

Daha ileriyi fark etsem de (yayınladığımda ortalıkta yoktu), var month = month [mm - 1] || ''; Hangisi daha düzgün olurdu.
NeilElliott-NSDev

4
var getMonth=function(month){
   //Return string to number.
    var strMonth = ['January', 'February', 'March',
             'April', 'May', 'June', 'July',
             'August', 'September', 'October',
             'November', 'December'
            ];
    //return number to string.
    var intMonth={'January':1, 'February':2, 'March':3,
             'April':4, 'May':5, 'June':6, 'July':7,
             'August':8, 'September':9, 'October':10,
             'November':11, 'December':12
            };
    //Check type and return 
    return (typeof month === "number")?strMonth[month-1]:intMonth[month]
}

4

@Vidriduch gibi, günümüz bağlamında kodun i20y'nin ("uluslararası hale getirilebilirlik") öneminin altını çizmek ve üniter testle birlikte aşağıdaki kısa ve sağlam çözümü önermek istiyorum.

function num2month(month, locale) {
    if (month != Math.floor(month) || month < 1 || month > 12)
        return undefined;
    var objDate = new Date(Math.floor(month) + "/1/1970");
    return objDate.toLocaleString(locale, {month: "long"});
}

/* Test/demo */
for (mm = 1; mm <= 12; mm++)
    document.writeln(num2month(mm, "en") + " " +
                     num2month(mm, "ar-lb") + "<br/>");
document.writeln(num2month("x", "en") + "<br/>");
document.writeln(num2month(.1, "en") + "<br/>");
document.writeln(num2month(12.5, "en" + "<br/>"));

Orijinal soruya olabildiğince yakın durmaya çalışıyorum, yani 1'den 12'ye kadar olan sayıları ay adlarına dönüştürmeye çalışıyorum, sadece bir özel durum için değil undefined, geçersiz argümanlar durumunda daha önce eklenen bazı eleştirileri ve diğerlerinin içeriğini kullanarak geri dönüyorum. Yanıtlar. (Değişim undefinediçin ''durumunda, önemsiz kesin eşleştirme gereklidir.)


0

Ben gitmek istiyorum wasmoo 'ın çözümü, ancak bu gibi ayarlayın:

var month = [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December'
][mm-1] || '';

Bu tam olarak aynı koddur, ancak farklı şekilde girintilidir ve IMO onu daha okunaklı kılar.

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.