如何缩短将数字转换为月份名称的开关盒?


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的答案是最合适的。这可能不是代码中需要Date操作的唯一部分(即使您显示的代码特别容易编码)。您应该认真考虑使用现有的,经过测试的日期库。
coredump

2
我不知道javascript,但是它没有哈希图,例如Python的字典或C ++的std :: map吗?
蒙面侠

28
这不是应该用于codereview.stackexchange.com吗?
Loko 2015年

2
如此多的答案通过不考虑默认的''来更改代码的行为,从而导致未定义的输出,这与原始代码不同。
Pieter B

2
这是不是一个重复的问题> :(这是要求一个完全不同的问题,答案可能是一样的,但是,
莱昂Gaban

Answers:


199

定义一个数组,然后按索引获取。

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

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

23
而不是mm - 1也可以将其设置undefined为第一个值(索引0),以便数组索引将与月份数字匹配
Touffy 2015年

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

77
@ mpez0我想我更愿意知道某人设法得出了第15个月的数据,而不是隐藏可能是不良数据的数据
Izkata 2015年

21
@Touffy我想坚持下去mm-1,这样months.length==12
Teepeemm 2015年

48
@Touffy我认为这不是品味问题,而是避免聪明代码的问题。想象一下自己正在阅读其他文章[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" }));

按照这个答案从大卫·斯托里的日期获取月份名称


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 2015年

3
这实际上是一个枚举(即使其不可变),将其定义为在JavaScript中var months = Object.freeze({'1': 'January', '2': 'February'}); //etc看到枚举?
亚历山大

1
@Alexander如果交换键和值,则是的,它类似于枚举。
但是我不是包装课

26

您可以改为创建一个数组并查找月份名称:

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


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

有关代码背后的合理性,请参见@CupawnTae的答案 || ''


而不是从0开始的索引,你可以继续undefined0var months = [ undefined, 'January','February','March', .....这样,您将使用month = months[mm];
Grijesh肖汉

@GrijeshChauhan:请避免使用“聪明”代码。下一个人的第一反应应该是wtf。只有一个月-1,长度将为13,wtf ^ 2。programmers.stackexchange.com/questions/91854/...
RvdK

19

小心!

第一行应立即触发警报:var month = '';-为什么将此变量初始化为空字符串,而不是nullundefined?它可能只是习惯代码或复制/粘贴的代码,但是除非您肯定知道,否则在重构代码时忽略它是不安全的。

如果您使用的月份名称的数组,并改变你的代码,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)2015年

这个答案是当场。其他大多数答案都以微妙的方式改变了代码的行为。这可能无关紧要,也可能变得很难找到错误。
Pieter B

嗯,所以最好将var初始化为undefined?如果类型被转换,是否可以节省性能?
Leon Gaban 2015年

2
@LeonGaban这与性能无关:最初的问题将变量初始化为空字符串,如果未选择有效月份,则将其保留在该字符串上,而此处的许多其他答案都忽略了这一事实,并通过undefined在输入为n时返回来更改了行为不是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' :
  '';

如果您之前还没有看到链式条件运算符,那么一开始看起来似乎很难理解。将其编写为表达式比原始代码更易于看清一个方面。显然,代码的目的是为变量赋值month


1
我也想建议这个。实际上,它在保持简洁的同时非常易读,并且对于稀疏映射和非数字键非常适用,而数组解决方案则不能。附言:我的回答中也有一个随机的无法解释的降票-可能是同一位路过的艺术家。
CupawnTae 2015年

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]
阳2015年

如果数组索引超出范围,将导致未定义!
NeilElliott-NSDev

months[mm - 1]将返回undefined超出范围的索引。由于undefined是虚假的,您最终将获得''的价值month
YingYang 2015年

如其他答案所述,您可以进一步简化此行:var month = months[mm - 1] || '';
YingYang 2015年

尽管我已经注意到进一步的发展(发布时并没有出现),但是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更具可读性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.