5

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

模式是:

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"

目标,我寻求的答案,是找到执行速度最快的方法,返回一个booleanwheretrue意味着模式是好的,false意味着模式是坏的。

这是我目前的解决方案

function matchesPattern(pattern) {
    if (pattern.length !== 12) {
        return false;
    }

    var i = 0,
        code;

    while (i < 12) {
        code = pattern.charCodeAt(i);

        if (i > 8 || i % 4 !== 3) {
            if (code < 48 || 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 上执行失败

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

仅因微优化而不同的答案很重要

如果它有效并且已添加到性能图表中,请不要更改您的答案。您可以提交多个答案。

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

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

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

没有使用任何 3rd 方库、jquery、undescore 等的解决方案,什么都没有。并不奇怪,但我认为有人可能已经尝试过了。

展开的循环似乎仍然是王道。许多人说现在没有必要,因为浏览器非常先进,但这次测试仍然表明它们是王者。

我要感谢所有参与这个问题的人,尤其是那些实际提交代码进行测试的人。

4

6 回答 6

3
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) != '-');
}
于 2013-05-02T14:32:11.573 回答
3

甚至比以前更快:

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只需要比较一次)

于 2013-05-02T16:31:32.720 回答
2

其他答案之一的轻微变化,但我相信内置字符类应该比自定义类稍快:

return /^\d{3}-\d{3}-\d{4}$/.test(phoneNumber);
于 2013-05-02T14:53:00.210 回答
2

声明一个正则表达式对象会预编译它以供将来使用。由于您正在循环几个测试字符串,因此首先在函数外部实例化对象应该会更好:

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

那么函数将是:

function matchesPattern(pattern) {
    return rex.test(pattern);
}
于 2013-05-02T15:09:53.560 回答
2

您可以为此使用正则表达式:

if(/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/.test('123-456-7890'))
    //ok
else
    //not ok
于 2013-05-02T13:05:21.713 回答
1

非常快:

   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;
}
于 2013-05-02T13:51:46.027 回答