用于测试固定电话号码模式的最快方法

因此,挑战在于我们正在尝试检测字符串是否与固定电话号码模式匹配,这是一个简单的字符串模式。

模式是:

ddd-ddd-dddd 

其中“d”代表十进制数字而减号代表自身,“ – ”

当前用于测试的模式是,但如果感觉没有足够的模式来揭穿错误的格式,则可以增加。

 "012-345-6789" "0124-345-6789" "012-3456-6789" "012-345-67890" "01a-345-6789" "012-34B-6789" "012-345-678C" "012" 

我寻求的目标是找到执行速度最快的方法返回一个boolean ,其中true表示模式是好的,而false表示模式是坏的。

这是我目前的解决方案

 function matchesPattern(pattern) { if (pattern.length !== 12) { return false; } var i = 0, code; while (i  8 || i % 4 !== 3) { if (code  57) { return false; } } else if (code !== 45) { return false; } i += 1; } return true; } 

它可以在jsfiddle上与测试模式一起使用

我有一个jsperf创建,我将添加进一步建议的方法,以便可以比较方法的执行速度,以确定哪个是最快的

您的方法可以是将在浏览器中执行的任何有效的JavaScript代码,如果您愿意,可以使用ECMA5并定位现代浏览器,或者使用跨浏览器标准,如果不在IE6上运行,则答案将被视为不正确例如。 您也可以使用任何您想要的第三方库,即jquery,lodash,下划线等。最后的要求是代码必须不能在Chrome v25或Firefox v20上执行

我有什么不清楚的地方请随时发表评论,我会更新我的问题以澄清。

只有微优化才有区别的答案

如果它的工作已经添加到性能图表中,请不要更改您的答案。 您可以提交1个以上的答案。

更新:好一周过去了,现在是时候宣布我将选择的答案。

从这次练习中学到了什么?

与手工构建的javascript例程相比,似乎正则表达式相对较慢,尽管对于大多数任务而言足够快。 (至少对于小字符串模式)

没有任何解决方案使用任何第三方库,jquery,非核心等等。 这并不令人意外,但我有人可能已经尝试过了。

展开的循环似乎仍然是王道。 很多人说现在没有必要因为浏览器如此先进,但是这个测试仍然表明它们是最重要的。

我要感谢所有参与此问题的人,特别是那些实际提交测试代码的人。

甚至比以前更快:

 function tecjam5(pattern) { var c; return !(pattern.length != 12 || !(((c=pattern.charCodeAt(2))>>3) == 6 || (c>>1) == 28) || !(((c=pattern.charCodeAt(4))>>3) == 6 || (c>>1) == 28) || !(((c=pattern.charCodeAt(11))>>1) == 28 || (c>>3) == 6) || !(((c=pattern.charCodeAt(0))>>3) == 6 || (c>>1) == 28) || !(((c=pattern.charCodeAt(1))>>3) == 6 || (c>>1) == 28) || !(((c=pattern.charCodeAt(5))>>3) == 6 || (c>>1) == 28) || !(((c=pattern.charCodeAt(6))>>3) == 6 || (c>>1) == 28) || !(((c=pattern.charCodeAt(8))>>3) == 6 || (c>>1) == 28) || !(((c=pattern.charCodeAt(9))>>3) == 6 || (c>>1) == 28) || !(((c=pattern.charCodeAt(10))>>1) == 28 || (c>>3) == 6) || pattern.charAt(3) != '-' || pattern.charAt(7) != '-'); } 

(简称:每个数字<8只需要比较一次)

 function whyNotBeSilly(pattern) { return !(pattern.length !== 12 || (code = pattern.charCodeAt(0)) < 48 || code > 57 || (code = pattern.charCodeAt(1)) < 48 || code > 57 || (code = pattern.charCodeAt(2)) < 48 || code > 57 || (code = pattern.charCodeAt(4)) < 48 || code > 57 || (code = pattern.charCodeAt(5)) < 48 || code > 57 || (code = pattern.charCodeAt(6)) < 48 || code > 57 || (code = pattern.charCodeAt(8)) < 48 || code > 57 || (code = pattern.charCodeAt(9)) < 48 || code > 57 || (code = pattern.charCodeAt(10)) < 48 || code > 57 || (code = pattern.charCodeAt(11)) < 48 || code > 57 || pattern.charAt(3) != '-' || pattern.charAt(7) != '-'); } 

你可以使用正则表达式:

 if(/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/.test('123-456-7890')) //ok else //not ok 

其中一个答案略有不同,但我相信内置字符类应该比自定义字符快一点:

 return /^\d{3}-\d{3}-\d{4}$/.test(phoneNumber); 

声明正则表达式对象会预编译它以供将来使用。 因为你循环遍历几个测试字符串,所以它应该更好地在函数外部实例化对象:

 var rex = /^\d{3}-\d{3}-\d{4}$/; 

那么函数将是:

 function matchesPattern(pattern) { return rex.test(pattern); } 

非常快:

  function tecjam3(pattern) { if (pattern.length !== 12) { return false; } code = pattern.charCodeAt(0); if (code < 48 || code > 57) return false; code = pattern.charCodeAt(1); if (code < 48 || code > 57) return false; code = pattern.charCodeAt(2); if (code < 48 || code > 57) return false; code = pattern.charCodeAt(4); if (code < 48 || code > 57) return false; code = pattern.charCodeAt(5); if (code < 48 || code > 57) return false; code = pattern.charCodeAt(6); if (code < 48 || code > 57) return false; code = pattern.charCodeAt(8); if (code < 48 || code > 57) return false; code = pattern.charCodeAt(9); if (code < 48 || code > 57) return false; code = pattern.charCodeAt(10); if (code < 48 || code > 57) return false; code = pattern.charCodeAt(11); if (code < 48 || code > 57) return false; if (pattern.charAt(3) != '-' || pattern.charAt(7) != '-') return false; return true; }