格式化电话号码,并不像看到的那么简单
问题
给出一个整数数组,长度为10,如:[1,2,3,4,5,6,7,8,9,0],按顺序转换成电话号码字符串,格式如下:
(123) 456-7890
这道问题看似很简单,解决思路也非常明了,我们尝试用javascript来解决这个问题。
思路一:拆分组合法
通常的做法是把数组按照输出格式中的各个部分的长度进行分割,如下:
第一组:1,2,3
第二组:4,5,6
第三组:7,8,9,0
Javascript中关于数组分割的函数最常用的是 slice 和 splice, 我们分别尝试使用二者,也能从中体会二者的区别。
首先,利用slice:
function createPhoneNumber(numbers){ return "("+numbers.slice(0,3).join('')+") "+numbers.slice(3,6).join('')+"-"+numbers.slice(6,10).join(''); }
这个解决思路看起来不错,简洁且容易理解。
其次,利用splice:
function createPhoneNumber(numbers){
return "("+numbers.splice(0,3).join('')+") "+numbers.splice(0,3).join('')+"-"+numbers.splice(0,4).join('');
}
因为每次splice操作都会对原数组造成破坏,这是一个数组剪切操作, 每次splice的参数都需要事先在头脑中计算得出 。该方法在易读方面不如前者。
也可以先把数组转换成字符串,然后再拆分组合,看起来更自然一些。
function createPhoneNumber(numbers){ var numbers=numbers.join(''); return "("+numbers.substring(0,3)+") "+numbers.substring(3,6)+"-"+numbers.substring(6,10); }
还可以利用 string.format() 结合 Array.slice()函数达成拆分组合的目的。
function createPhoneNumber(numbers){
return "({0}) {1}-{2}".format(
numbers.slice(0,3).join(''),
numbers.slice(3,6).join(''),
numbers.slice(6).join('')
)
}
思路二:替换法
我们知道最终的电话号码格式为:(xxx) xxx-xxxx
那么是否可以用替换法来实现该函数呢,把上述字符串中的每个x都相应地换成具体数值就可以了。
为此我们需要先构造一个字符串变量:var phoneFormat="(xxx) xxx-xxxx"
然后循环数组,逐个替换掉其中的x即可,我们知道javascript中的replace函数一次只能替换一个字符,充分利用这一点就可以达到我们的目的。
function createPhoneNumber(numbers){ var phoneFormat="(xxx) xxx-xxxx"; for(var i=0;i<numbers.length;i++){ phoneFormat=phoneFormat.replace('x',numbers[i]); } return phoneFormat; }
利用 Array.forEach() 函数会使代码更简洁:
function createPhoneNumber(numbers){ var phoneFormat="(xxx) xxx-xxxx"; numbers.forEach(d=>{ phoneFormat=phoneFormat.replace('x',d); }); return phoneFormat; }
思路三:利用正则表达式
作为开发人员,第一眼看到这个问题时应该会本能地想到正则表达式,作为文本处理的利器,我们应该时常磨练使用。
电话号码的最终格式为:(xxx) xxx-xxxx , 正则表达式可由三部分组成:(group1) group2-group3。
构建正则表达式如下:
/(\d{3})(\d{3})(\d{4})/
然后利用replace函数输出结果。
function createPhoneNumber(numbers){ return numbers.join('').replace(/(\d{3})(\d{3})(\d{4})/,'($1) $2-$3'); }
正则表达式还可以更简洁一些:
function createPhoneNumber(numbers){ return numbers.join('').replace(/(...)(...)(.*)/, '($1) $2-$3'); }
如果对ES6中的箭头函数比较了解,正则表达式的替换过程还可以写为:
function createPhoneNumber(numbers){ const p = () => numbers.shift(); return "(xxx) xxx-xxxx".replace(/x/g, p); }
思路四:模板字符串
除了以上三种比较传统的方法外,我们还可以借助Javascript的模板技术,实现字符串的输出。
首先把数组转换成字符串,如:1234567890,利用string.substr()或string.substring()字符串处理函数结合模板字符串技术输出结果,其实就是取代传统字符串组合运算(+)。
function createPhoneNumber (numbers) { numbers = numbers.join('') return `(${numbers.substr(0, 3)}) ${numbers.substr(3, 3)}-${numbers.substr(6, 10)}` }
总结
编程的魅力就在于此,即使面对一个非常简单的电话号码格式化输出问题,我们都可以给出多种解决方法。可以想见,那些更复杂的问题,存在的解决途径一定更加的五光十色,光怪陆离,这也许就是程序编写的魅力所在:通向罗马的道路千条万条,它们的区别不仅仅是代码行数的多少!