Làm thế nào để rút ngắn khối chuyển đổi trường hợp chuyển đổi một số thành tên tháng?


110

Có cách nào để viết điều này trên ít dòng hơn, nhưng vẫn dễ đọc không?

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
Câu trả lời của IMHO vidriduch là thích hợp nhất. Đây có lẽ không phải là phần duy nhất của mã của bạn yêu cầu thao tác Ngày tháng (mặc dù phần bạn đã hiển thị là đặc biệt dễ viết). Bạn nên xem xét nghiêm túc việc sử dụng các thư viện Date đã được thử nghiệm, hiện có.
coredump

2
Tôi không biết javascript, nhưng nó không có bản đồ băm, như từ điển của Python hoặc std :: map của C ++?
Masked Man

28
Điều này không được cho là dành cho codereview.stackexchange.com ?
Loko

2
Vì vậy, nhiều câu trả lời thay đổi hành vi của mã bằng cách không tính đến giá trị mặc định '' dẫn đến kết quả đầu ra không xác định, khác với những gì ban đầu làm.
Pieter B

2
Đây không phải là một câu hỏi trùng lặp> :( đây là một câu hỏi hoàn toàn khác, tuy nhiên câu trả lời có thể giống nhau.
Leon Gaban

Câu trả lời:


199

Xác định một mảng, sau đó lấy theo chỉ mục.

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

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

23
thay vì mm - 1bạn cũng có thể đặt undefinedlàm giá trị đầu tiên (chỉ số 0) để các chỉ số mảng sẽ khớp với số tháng
Touffy

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

77
@ mpez0 Tôi nghĩ rằng tôi muốn biết rằng ai đó đã quản lý để đưa ra tháng số 15, hơn là giấu những gì có thể là dữ liệu xấu
Izkata

21
@Touffy Tôi nghĩ tôi sẽ gắn bó với mm-1, vì vậy điều đó months.length==12.
Teepeemm

48
@Touffy Tôi cho rằng đó không phải là vấn đề sở thích, mà là vấn đề tránh mã thông minh . Hãy tưởng tượng bạn đang đọc một số người khác [undefined, 'January', 'February', ...]- Tôi tốt nhất phản ứng đầu tiên của bạn là WTF ?! , thường không phải là một dấu hiệu tốt ...
magiculixx

81

những gì về việc không sử dụng mảng nào cả :)

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

theo câu trả lời này Lấy tên tháng từ Ngày từ David Storey


2
Với tuyên bố vấn đề được đề cập, câu trả lời của bạn không thực sự giải quyết vấn đề đó mà là một số giải pháp khác có thể đúng trong một ngữ cảnh khác. Câu trả lời được chọn vẫn là tốt nhất và hiệu quả nhất.
TechMaze

6
Chỉ new Date("2009-11-10")định dạng được đảm bảo sẽ được phân tích cú pháp (xem thông số kỹ thuật này: ecma-international.org/publications/standards/Ecma-262.htm ). Các định dạng ngày tháng khác (bao gồm cả một định dạng trong câu trả lời của bạn) có thể được phân tích cú pháp nếu trình duyệt chọn như vậy và do đó không thể di động.
jb.

58

Thử cái này:

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

Lưu ý rằng đó mmcó thể là một số nguyên hoặc một chuỗi và nó sẽ vẫn hoạt động.

Nếu bạn muốn các khóa không tồn tại dẫn đến chuỗi trống ''(thay vì undefined), thì hãy thêm dòng này:

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

JSFiddle .


4
Trên các tập dữ liệu lớn hơn "các tháng trong năm", điều này có thể sẽ hiệu quả hơn.
DGM

3
Đây thực sự là một enum (tức là làm cho nó bất biến), hãy định nghĩa nó là var months = Object.freeze({'1': 'January', '2': 'February'}); //etcSee Enum trong JavaScript?
Alexander

1
@Alexander Nếu bạn hoán đổi khóa và giá trị, thì có, nó tương tự như enum.
But I'm Not A Wrapper Class

26

Thay vào đó, bạn có thể tạo một mảng và tra cứu tên tháng:

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


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

Xem câu trả lời của @CupawnTae để biết lý do đằng sau mã || ''


chứ không phải là bắt đầu với 0 chỉ số bạn có thể giữ undefined0 như var months = [ undefined, 'January','February','March', .....Bằng cách này bạn sẽ sử dụngmonth = months[mm];
Grijesh Chauhan

@GrijeshChauhan: vui lòng tránh mã 'thông minh'. Phản ứng đầu tiên của người tiếp theo sẽ là wtf. Nó chỉ là '-1', tháng. Độ dài sau đó sẽ là 13, wtf ^ 2. programmers.stackexchange.com/questions/91854/…
RvdK

19

Hãy cẩn thận!

Điều sẽ ngay lập tức kích hoạt chuông cảnh báo là dòng đầu tiên: var month = '';- tại sao biến này được khởi tạo thành một chuỗi rỗng, thay vì nullhoặc undefined? Nó có thể chỉ là do thói quen hoặc sao chép / dán mã, nhưng trừ khi bạn biết chắc chắn điều đó, nếu không sẽ không an toàn khi bạn đang cấu trúc lại mã.

Nếu bạn sử dụng một mảng tên tháng và thay đổi mã của bạn thành var month = months[mm-1];bạn đang thay đổi hành vi, bởi vì bây giờ đối với các số nằm ngoài phạm vi hoặc các giá trị không phải số, monthsẽ như vậy undefined. Bạn có thể biết rằng điều này là tốt, nhưng có nhiều tình huống mà điều này sẽ trở nên tồi tệ.

Ví dụ: giả sử bạn switchđang ở trong một hàm monthToName(mm)và ai đó đang gọi hàm của bạn như thế này:

var monthName = monthToName(mm);

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

Bây giờ nếu bạn chuyển sang sử dụng một mảng và quay lại monthName[mm-1], mã gọi sẽ không còn hoạt động như dự kiến ​​và nó sẽ gửi undefinedcác giá trị khi nó được cho là hiển thị cảnh báo. Tôi không nói đây là mã tốt , nhưng trừ khi bạn biết chính xác mã đang được sử dụng như thế nào, bạn không thể đưa ra giả định.

Hoặc có thể quá trình khởi tạo ban đầu đã ở đó bởi vì một số mã ở dòng sâu hơn giả định rằng đó monthsẽ luôn là một chuỗi và thực hiện điều gì đó giống như month.length- điều này sẽ dẫn đến một ngoại lệ được ném ra trong các tháng không hợp lệ và có khả năng giết chết hoàn toàn tập lệnh gọi.

Nếu bạn làm biết toàn bộ bối cảnh - ví dụ đó là tất cả các mã của riêng bạn, và không ai khác là bao giờ sẽ sử dụng nó, bạn tin tưởng mình không quên bạn thực hiện đôi khi sự thay đổi trong tương lai - nó có thể là an toàn để thay đổi hành vi như thế này, nhưng rất nhiều lỗi đến từ kiểu giả định rằng trong cuộc sống thực, tốt hơn hết bạn nên lập trình phòng thủ và / hoặc ghi lại hành vi một cách kỹ lưỡng.

Câu trả lời của Wasmoo rất đúng (CHỈNH SỬA: một số câu trả lời khác, bao gồm cả câu được chấp nhận, hiện cũng đã được sửa) - bạn có thể sử dụng months[mm-1] || ''hoặc nếu bạn muốn làm cho nó rõ ràng hơn trong nháy mắt những gì đang xảy ra, đại loại như:

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
Không ai khác đã đề cập đến sự thay đổi trong hành vi, vì vậy điều này cần được tính đến khi mã bao thanh toán lại.
Mauro

Câu trả lời này là đúng. Hầu hết các câu trả lời khác thay đổi hành vi của mã một cách tinh vi. Điều này có thể không thành vấn đề hoặc nó có thể trở thành lỗi khó phát hiện.
Pieter B

Ah vì vậy tốt nhất bạn nên init một var để undefined? Điều đó có tiết kiệm hiệu suất nếu loại được chuyển đổi không?
Leon Gaban

2
@LeonGaban đó không phải là về hiệu suất: câu hỏi ban đầu khởi tạo biến thành một chuỗi trống và để nó ở đó nếu không có tháng hợp lệ nào được chọn, trong khi rất nhiều câu trả lời khác ở đây đã bỏ qua thực tế đó và thay đổi hành vi bằng cách trả về undefinedkhi đầu vào không có 't 1..12. Ngoại trừ trong những trường hợp rất đặc biệt, hành vi đúng mực sẽ luôn nâng cao hiệu suất.
CupawnTae

17

Để có sự hoàn chỉnh, tôi muốn bổ sung cho các câu trả lời hiện tại. Về cơ bản, bạn có thể bỏ qua breaktừ khóa và trực tiếp trả về một giá trị thích hợp. Chiến thuật này hữu ích nếu giá trị không thể được lưu trữ trong bảng tra cứu được tính toán trước.

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

Một lần nữa, việc sử dụng bảng tra cứu hoặc các hàm ngày sẽ ngắn gọn hơn và tốt hơn về mặt chủ quan .


16

Bạn có thể làm điều đó bằng cách sử dụng một mảng:

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

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

12

Đây là một tùy chọn khác chỉ sử dụng 1 biến và vẫn áp dụng giá trị mặc định ''khi mmnằm ngoài phạm vi.

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

Kiểm tra phạm vi và ném một ngoại lệ cũng có thể hoạt động. Và trả về "Lỗi" hoặc "Không xác định" có thể thay thế cho chuỗi trống.
ChuckCottrill

9

Bạn có thể viết nó dưới dạng một biểu thức thay vì một công tắc, bằng cách sử dụng các toán tử điều kiện:

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

Nếu bạn chưa từng thấy các toán tử có điều kiện được xâu chuỗi trước đó, điều này có vẻ khó đọc hơn lúc đầu. Viết nó dưới dạng một biểu thức làm cho một khía cạnh thậm chí còn dễ nhìn hơn so với mã gốc; rõ ràng mục đích của mã là gán một giá trị cho biến month.


1
Tôi cũng có ý đề nghị điều này. Nó thực sự rất dễ đọc trong khi vẫn ngắn gọn và sẽ hoạt động tốt cho các ánh xạ thưa thớt và các phím không phải số, điều mà giải pháp mảng không làm được. Tái bút Tôi cũng nhận được một phản đối ngẫu nhiên không giải thích được cho câu trả lời của mình - có lẽ là cùng một nghệ sĩ lái xe.
CupawnTae

6

Dựa trên câu trả lời của Cupawn Tae trước đó, tôi rút gọn nó thành:

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

Ngoài ra, có, tôi đánh giá cao, ít đọc hơn:

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

Bạn có thể bỏ qua (!!months[mm - 1])và chỉ cần làm months[mm - 1].
YingYang

Điều đó sẽ dẫn đến không xác định nếu chỉ số mảng nằm ngoài phạm vi!
NeilElliott-NSDev

months[mm - 1]sẽ trả về undefinedchỉ mục nằm ngoài phạm vi. Vì undefinedlà giả, bạn sẽ kết thúc bằng ''giá trị của month.
YingYang

Như đã nêu trong câu trả lời khác bạn có thể đơn giản hóa dòng này thậm chí nhiều hơn:var month = months[mm - 1] || '';
YingYang

Mặc dù tôi đã nhận thấy thêm (không phải khoảng thời gian tôi đăng), var month = months [mm - 1] || ''; Mà sẽ vẫn gọn gàng hơn.
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

Giống như @vidriduch, tôi muốn nhấn mạnh tầm quan trọng của mã i20y ("tính quốc tế") trong bối cảnh ngày nay và đề xuất giải pháp ngắn gọn và mạnh mẽ sau đây cùng với thử nghiệm đơn nhất.

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

Tôi cố gắng bám sát nhất có thể với câu hỏi ban đầu, tức là chuyển đổi các số từ 1 đến 12 thành tên tháng, không chỉ cho một trường hợp đặc biệt, mà trả lại undefinedtrong trường hợp các đối số không hợp lệ, sử dụng một số chỉ trích đã được thêm trước đây và nội dung của các các câu trả lời. (Thay đổi từ undefinedthành ''là nhỏ, trong trường hợp cần đối sánh chính xác .)


0

Tôi muốn giải pháp của wasmoo , nhưng điều chỉnh nó như thế này:

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

Nó thực sự là cùng một mã, nhưng được thụt lề khác nhau, IMO làm cho nó dễ đọc hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.