วิธีการย่อบล็อกกรณีสลับการแปลงตัวเลขเป็นชื่อเดือน


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
คำตอบของ IMHO vidriduchเหมาะสมที่สุด นี่อาจไม่ใช่ส่วนเดียวของโค้ดของคุณที่ต้องใช้การปรับแต่งวันที่ (แม้ว่าโค้ดที่คุณแสดงจะง่ายต่อการเขียนโค้ดก็ตาม) คุณควรพิจารณาอย่างจริงจังโดยใช้ไลบรารีวันที่ทดสอบที่มีอยู่
coredump

2
ฉันไม่รู้จัก javascript แต่ไม่มีแฮชแมปเช่นพจนานุกรมของ Python หรือ std :: map ของ C ++ หรือไม่
Masked Man

28
นี่ไม่ใช่สำหรับcodereview.stackexchange.comใช่ไหม
Loko

2
มีคำตอบมากมายที่เปลี่ยนพฤติกรรมของโค้ดโดยไม่คำนึงถึงค่าเริ่มต้น '' ซึ่งส่งผลให้เกิดผลลัพธ์ที่ไม่ได้กำหนดซึ่งแตกต่างจากสิ่งที่ต้นฉบับทำ
Pieter B

2
นี่ไม่ใช่คำถามที่ซ้ำกัน> :( นี่เป็นการถามคำถามที่แตกต่างไปจากเดิมอย่างสิ้นเชิง แต่คำตอบอาจจะเหมือนกัน
Leon Gaban

คำตอบ:


199

กำหนดอาร์เรย์แล้วรับด้วยดัชนี

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

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

23
แทนmm - 1นอกจากนี้คุณยังสามารถตั้งค่าundefinedเป็นค่าแรก (ดัชนี 0) ดังนั้นดัชนีอาร์เรย์จะตรงกับตัวเลขเดือน
Touffy

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

77
@ mpez0 ฉันคิดว่าฉันอยากรู้ว่ามีคนจัดการให้เกิดเดือนที่ 15 มากกว่าซ่อนสิ่งที่อาจเป็นข้อมูลที่ไม่ดี
Izkata

21
@Touffy ผมคิดว่าผมจะติดกับเพื่อให้mm-1 months.length==12
Teepeemm

48
@Touffy ฉันจะยืนยันว่าไม่ได้เป็นเรื่องของรสชาติ แต่เรื่องของการหลีกเลี่ยงรหัสฉลาด ลองนึกภาพว่าตัวเองกำลังอ่านของคนอื่นอยู่[undefined, 'January', 'February', ...]- ปฏิกิริยาแรกที่ดีที่สุดของคุณคือWTF?! ซึ่งมักจะไม่ใช่สัญญาณที่ดี ...
miraculixx

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

ตามคำตอบนี้รับชื่อเดือนจาก Dateจาก David Storey


2
จากคำชี้แจงปัญหาที่เป็นปัญหาคำตอบของคุณไม่ได้เป็นการแก้ปัญหานั้นจริงๆ แต่มีวิธีแก้ปัญหาที่แตกต่างกันซึ่งอาจถูกต้องในบริบทที่แตกต่างกัน คำตอบที่เลือกยังคงเป็นคำตอบที่ดีที่สุดและมีประสิทธิภาพที่สุด
TechMaze

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

3
นี่คือ enum อย่างมีประสิทธิภาพ (เช่นทำให้ไม่เปลี่ยนรูป) กำหนดเป็นvar months = Object.freeze({'1': 'January', '2': 'February'}); //etcSee Enums ใน JavaScript?
Alexander

1
@ อเล็กซานเดอร์ถ้าคุณสลับคีย์และค่าใช่มันจะคล้ายกับ enum
But I'm Not A Wrapper Class

26

คุณสามารถสร้างอาร์เรย์แทนและค้นหาชื่อเดือน:

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


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

ดูคำตอบโดย @CupawnTae สำหรับเหตุผลที่อยู่เบื้องหลังรหัส || ''


แทนที่จะเริ่มต้นด้วย 0 ดัชนีคุณสามารถเก็บundefinedที่0 เป็น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หรือ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 to undefined? จะประหยัดประสิทธิภาพหรือไม่หากประเภทได้รับการแปลง
Leon Gaban

2
@LeonGaban ไม่เกี่ยวกับประสิทธิภาพ: คำถามเดิมเริ่มต้นตัวแปรเป็นสตริงว่างและปล่อยไว้ที่นั้นหากไม่ได้เลือกเดือนที่ถูกต้องในขณะที่คำตอบอื่น ๆ จำนวนมากที่นี่ไม่สนใจข้อเท็จจริงนั้นและเปลี่ยนพฤติกรรมโดยส่งคืนundefinedเมื่ออินพุตไม่ได้ 't 1..12. ยกเว้นในมากกรณีพิเศษปั้นพฤติกรรมที่ถูกต้องประสิทธิภาพการทำงานทุกครั้ง
CupawnTae

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

การตรวจสอบช่วงและการทิ้งข้อยกเว้นก็สามารถใช้ได้เช่นกัน และการส่งคืน "Error" หรือ "Undefined" อาจเป็นทางเลือกแทนสตริงว่าง
ChuckCottrill

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

หากคุณไม่เคยเห็นตัวดำเนินการตามเงื่อนไขที่ถูกล่ามโซ่มาก่อนสิ่งนี้อาจดูยากกว่าในตอนแรก การเขียนเป็นนิพจน์ทำให้มองเห็นแง่มุมหนึ่งได้ง่ายกว่าโค้ดดั้งเดิม monthก็เป็นที่ชัดเจนว่าเจตนาของรหัสคือการกำหนดค่าให้กับตัวแปร


1
ฉันตั้งใจจะแนะนำสิ่งนี้เช่นกัน มันอ่านได้ง่ายมากในขณะที่ยังคงกระชับและจะทำงานได้ดีสำหรับการแมปแบบเบาบางและคีย์ที่ไม่ใช่ตัวเลขซึ่งโซลูชันอาร์เรย์ไม่ได้ ป.ล. ฉันได้รับการโหวตลงคะแนนแบบสุ่มที่ไม่ได้อธิบายในคำตอบของฉันด้วยเช่นกันซึ่งอาจเป็นศิลปินขับรถคนเดียวกัน
CupawnTae

6

จากคำตอบของ Cupawn Taeก่อนหน้านี้ฉันจะย่อให้สั้นลงเป็น:

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

นั่นจะส่งผลให้ไม่ได้กำหนดหากดัชนีอาร์เรย์อยู่นอกช่วง!
NeilElliott-NSDev

months[mm - 1]จะส่งกลับundefinedสำหรับดัชนีที่อยู่นอกช่วง ตั้งแต่undefinedเป็น falsy คุณจะจบลงด้วยการเป็นค่าของ'' month
YingYang

ตามที่ระบุไว้ในคำตอบอื่น ๆ คุณสามารถทำให้บรรทัดนี้ง่ายยิ่งขึ้น:var month = months[mm - 1] || '';
YingYang

แม้ว่าฉันจะสังเกตเห็นมากขึ้น (ไม่ได้อยู่ในช่วงที่ฉันโพสต์) var month = months [mm - 1] || ''; ซึ่งจะยังคงเป็นที่เรียบร้อย
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 ฉันต้องการขีดเส้นใต้ความสำคัญของ 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 ถึง 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.