数値を月名に変換するスイッチケースブロックを短縮する方法


110

これを少ない行で書く方法はありますが、それでも簡単に読むことができますか?

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
私見vidriduchの答えが最も適切です。これはおそらく、日付の操作を必要とするコードの唯一の部分ではありません(表示したものは特にコーディングが簡単ですが)。既存のテスト済み日付ライブラリの使用を真剣に検討する必要があります。
コアダンプ2015

2
JavaScriptはわかりませんが、Pythonの辞書やC ++のstd :: mapのようなハッシュマップはありませんか?
仮面の男

28
これはcodereview.stackexchange.comを想定しているのではありませんか?
ロコ

2
多くの答えは、デフォルトの ''を考慮に入れずにコードの動作を変更し、未定義の出力を生成します。これは、元の動作とは異なります。
Pieter B

2
これは、ない重複質問> :(これが答えはしかし、同じであってもよい、完全に異なる質問をしている。
レオン・ギャバン

回答:


199

配列を定義し、インデックスで取得します。

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

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

23
代わりに、最初の値(インデックス0)としてmm - 1設定undefinedして、配列のインデックスが月の番号と一致するようにすることもできます
Touffy

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

77
@ mpez0おそらく悪いデータを隠すよりも、誰かが月15を考え出すことができたことを知っているほうがいいと思う
イズカタ

21
@Touffy私はに固執すると思うmm-1ので、、 months.length==12
Teepeemm 2015

48
@タフィー私はそれは好みの問題ではなく、賢いコード避ける問題だと主張します。他の本を読んでいると想像してみてください[undefined, 'January', 'February', ...]-私の最初の反応はWTFですか?、これは通常良い兆候ではありません...
miraculixx 2015

81

配列をまったく使用しないのはどうですか:)

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" }));

この回答に従って、David Storey からDateから月の名前を取得します


2
問題の問題文を考えると、あなたの答えは実際にその問題を解決するのではなく、異なる状況では正しいかもしれないいくつかの異なる解決策です。選択された答えは、依然として最良かつ最も効率的です。
TechMaze、2015

6
new Date("2009-11-10")解析のみが保証されている形式(この仕様を参照:ecma-international.org/publications/standards/Ecma-262.htm)。他の日付形式(回答に含まれているものを含む)は、ブラウザーが選択した場合に解析される可能性があるため、移植できません。
jb。

58

これを試して:

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

mm整数または文字列にすることができ、それはまだ動作します。

存在しないキーの結果を''(ではなくundefined)空の文字列にする場合は、次の行を追加します。

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

JSFiddle


4
「年間の月」よりも大きなデータセットでは、これはおそらくより効率的です。
DGM 2015

3
これは実質的に列挙型(つまり、不変にする)であり、var months = Object.freeze({'1': 'January', '2': 'February'}); //etcJavaScriptで
アレクサンダー

1
@Alexanderキーと値を入れ替えると、はい、それは列挙型に似ています。
しかし、私はラッパークラスではありません

26

代わりに配列を作成し、月の名前を検索できます。

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


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

コードの背後にある合理的な理由については@CupawnTaeによる回答を参照してください || ''


ではなく、あなたが保つことができる0インデックスとスタートundefined0 のようにvar months = [ undefined, 'January','February','March', .....使用します。このようにmonth = months[mm];
Grijesh Chauhan

@GrijeshChauhan:「賢い」コードは避けてください。次の人の最初の反応はwtfでしょう。これは、 '-1'の月数です。長さは13、wtf ^ 2になります。programmers.stackexchange.com/questions/91854/...
RvdK

19

注意してください!

アラームベルをすぐにトリガーする必要があるのは、最初の行ですvar month = '';。- nullまたはor ではなく、なぜこの変数が空の文字列に初期化されるのundefinedですか。それは単に習慣であるか、コードをコピーして貼り付けただけかもしれませんが、確実にそれを知らない限り、コードをリファクタリングするときにそれを無視するのは安全ではありません。

月の名前の配列を使用してコードをvar month = months[mm-1];変更すると、動作が変更されます。これは、範囲外の数値または非数値の場合はにmonthなるためundefinedです。これは大丈夫だと知っているかもしれませんが、これが悪い状況がたくさんあります。

たとえば、あなたswitchが関数の中monthToName(mm)にいて、誰かがあなたの関数を次のように呼び出しているとします。

var monthName = monthToName(mm);

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

配列を使用してを返すように変更するとmonthName[mm-1]、呼び出し元のコードは意図したとおりに機能せずundefined、警告を表示することになっているときに値を送信します。これが良いコードであると言っているわけではありませんが、コードがどのように使用されているかを正確に知らない限り、仮定を立てることはできません。

あるいは、元の初期化がそこにあったのは、行末のいくつかのコードがそれmonthが常に文字列であると想定し、month.lengthことを行ったためです。これにより、無効な月に例外がスローされ、呼び出しスクリプトが完全に終了する可能性があります。

あなたがいる場合行う全体の文脈を知っている-例えばそれは、すべて独自のコードだし、他に誰が今までそれを使用しようとしていない、あなたが信頼自身は、あなたが将来的に変更いつかを作ったことを忘れない-動作を変更することは安全かもしれこのように、しかし、あまりにも多くのバグは、実際には、防御的にプログラミングしたり、動作を完全に文書化したりする方がはるかに良いというこの種の仮定に起因します。

Wasmooの答えは正しくなります(編集:受け入れられたものを含む他のいくつかの答えも修正されました) -あなたはそれを使うことができます、months[mm-1] || ''またはあなたが一目で何が起こっているかを一目でもっと明らかにしたい場合:

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
動作の変更についてはまだ誰も言及していないため、コードをリファクタリングする際にはこれを考慮する必要があります。
Mauro

この答えは正解です。他のほとんどの答えは、コードの動作を微妙に変更します。これは問題にならないかもしれませんし、バグを見つけるのがイライラするほど難しくなるかもしれません。
Pieter B

ああだから、常にvarを初期化するのが最善undefinedですか?型が変換された場合、パフォーマンスを節約できますか?
Leon Gaban 2015

2
@LeonGabanそれはパフォーマンスではありません:元の質問は変数を空の文字列に初期化し、有効な月が選択されなかった場合はそのままにしましたが、他の多くの回答はその事実を無視しundefined、入力がなかったときに戻ることで動作を変更しました「T 1..12非常に例外的な状況を除いて、正しい動作は毎回パフォーマンスを上回ります。
CupawnTae 2015

17

完全を期すために、現在の回答を補足したいと思います。基本的に、breakキーワードを省略して直接適切な値を返すことができます。この方法は、事前に計算されたルックアップテーブルに値を格納できない場合に役立ちます。

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 '';
}

繰り返しになりますが、ルックアップテーブルや日付関数を使用する方が簡潔で主観的に優れています。


16

あなたは配列を使ってそれを行うことができます:

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

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

12

1つの変数のみを使用し、範囲外の''場合でもデフォルト値を適用する別のオプションを次に示しますmm

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

範囲チェックと例外のスローも機能する可能性があります。また、「エラー」または「未定義」を返すことは、空の文字列の代わりになる場合があります。
ChuckCottrill 2015

9

条件演算子を使用して、スイッチではなく式として記述できます。

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' :
  '';

これまでにチェーンされた条件演算子を見たことがない場合、これは最初は読みにくいように見えるかもしれません。式として記述すると、1つの側面が元のコードよりも見やすくなります。コードの目的が変数に値を割り当てることであることは明らかですmonth


1
私もこれを提案するつもりでした。簡潔でありながら、実際には非常に読みやすく、スパースマッピングや非数値キーでうまく機能しますが、配列ソリューションではうまくいきません。PS私は私の答えについても説明されていないランダムな反対投票を獲得しました-おそらく同じドライブバイアーティストです。
CupawnTae

6

前のクポーンテの答えに基づいて、私はそれを次のように短縮します。

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

あるいは、はい、読みやすくします。

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

スキップ(!!months[mm - 1])して単純に実行できますmonths[mm - 1]
YingYang 2015

配列のインデックスが範囲外の場合、結果は未定義になります!
NeilElliott-NSDev 2015

months[mm - 1]undefined範囲外のインデックスが返されます。undefinedは偽物なので''、の値としてになりますmonth
YingYang 2015

他の回答で述べたように、この行をさらに簡略化できます:var month = months[mm - 1] || '';
YingYang

私はさらに気づきましたが(投稿したときはそうではありませんでした)、var month = months [mm-1] || ''; それでもまだすっきりします。
NeilElliott-NSDev 2015

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と同様に、今日のコンテキストにおけるコードのi20y(「国際化可能性」)の重要性を強調し、以下の簡潔で堅牢なソリューションと単一テストを提案します。

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/>"));

私は元の質問にできるだけ近づくようにしています。つまり、1つの特殊なケースだけでなく、1から12の数字を月の名前に変換しますがundefined、無効な引数の場合は、以前に追加されたいくつかの批判と他のコンテンツを使用して返します。答えます。(からundefinedへの変更''は、正確な一致が必要場合に備えて簡単です。)


0

wasmooの解決策を探しますが、次のように調整します。

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

まったく同じコードですが、インデントが異なっており、IMOによって読みやすくなっています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.