Programming

숫자를 월 이름으로 변환하는 스위치 케이스 블록을 줄이는 방법은 무엇입니까?

procodes 2020. 7. 29. 20:56
반응형

숫자를 월 이름으로 변환하는 스위치 케이스 블록을 줄이는 방법은 무엇입니까?


더 적은 줄에 이것을 쓸 수 있지만 여전히 쉽게 읽을 수 있습니까?

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

배열을 정의한 다음 인덱스별로 가져옵니다.

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

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

배열을 전혀 사용하지 않는 것은 어떻습니까? :)

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의 날짜 에서 월 이름을 받으십시오.


이 시도:

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

참고 mm정수 또는 문자열이 될 수 있으며, 그것은 여전히 작동합니다.

존재하지 않는 키가 빈 문자열 ''() 대신에 결과를 얻으려면 undefined다음 행을 추가하십시오.

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

JSFiddle .


대신 배열을 만들고 월 이름을 조회 할 수 있습니다.

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


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

코드 뒤에 합리적인 이유는 @CupawnTae의 답변을 참조하십시오. || ''


조심해!

The thing that should immediately trigger alarm bells is the first line: var month = ''; - why is this variable being initialized to an empty string, rather than null or undefined? It may just have been habit or copy/pasted code, but unless you know that for sure, it is not safe to ignore it when you're refactoring code.

If you use an array of month names and change your code to var month = months[mm-1]; you are changing the behaviour, because now for numbers outside the range, or non-numeric values, month will be undefined. You may know that this is ok, but there are many situations where this would be bad.

For example, let's say your switch is in a function monthToName(mm), and someone is calling your function like this:

var monthName = monthToName(mm);

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

Now if you change to using an array and returning monthName[mm-1], the calling code will no longer function as intended, and it will submit undefined values when it is supposed to display a warning. I'm not saying this is good code, but unless you know exactly how the code is being used, you can't make assumptions.

Or maybe the original initialization was there because some code further down the line assumes that month will always be a string, and does something like month.length - this will result in an exception being thrown for invalid months and potentially kill the calling script completely.

If you do know the entire context - e.g. it's all your own code, and no-one else is ever going to use it, and you trust yourself not forget you made the change sometime in the future - it may be safe to change the behaviour like this, but soooo many bugs come from this kind of assumption that in real life you're far better off programming defensively and/or documenting the behaviour thoroughly.

Wasmoo's answer gets it right (EDIT: a number of other answers, including the accepted one, have now been fixed too) - you can use months[mm-1] || '' or if you would prefer to make it more obvious at a glance what's happening, something like:

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

var month;

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

For completeness I'd like to supplement to current answers. Basically, you can ommit the break keyword and directly return an appropriate value. This tactic is useful if the value cannot be stored in a precomputed look-up table.

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

Once again, using a look-up table or date functions is more succinct and subjectively better.


You could do it using an array:

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

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

Here's another option that uses only 1 variable and still applies the default value '' when mm is outside of range.

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

You could write it as an expression instead of a switch, using conditional operators:

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

If you haven't seen chained conditional operators before this may seem harder to read at first. Writing it as an expression makes one aspect even easier to see than the original code; it's clear that the intention of the code is to assign a value to the variable month.


Building on Cupawn Tae's answer previous I'd shorten it to :

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

Alternatively, yes, I appreciate, less readable:

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

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]
}

Like @vidriduch, I would like to underline the importance of i20y ("internationalisability") of code in nowadays' context and suggest the following concise and robust solution together with the unitary test.

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

I try to stay as close as possible to the original question, i.e. transform numbers 1 to 12 into month names, not only for one special case, but return undefined in case of invalid arguments, using some of the formerly added criticism to and contents of other answers. (The change from undefined to '' is trivial, in case exact matching is needed.)


I'd go for wasmoo's solution, but adjust it like this :

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

It is the exact same code, really, but differently indented, which IMO makes it more readable.

참고URL : https://stackoverflow.com/questions/29828098/how-to-shorten-switch-case-block-converting-a-number-to-a-month-name

반응형