前两天看到了一道前端面试题,《第11题:将数组扁平化并去除其中重复数据,最终得到一个升序且不重复的数组》,题目倒是没有多难,但是看了其中一个答案,感觉思路满满啊。
关于数组扁平化,前面写过一篇文章,在这里又看到了一个新的方法,在Array.prototype对象当中提供了一个方法:flat(depth)。
唯一的问题是,该方法目前虽然在部分浏览器当中能用,但是他还没有成为标准方法。他支持一个参数,指定嵌套数组中的结构深度,默认值为1。也就是扁平化多少层数组。
关于去重,在ES6当中,新增了一种语法结构Set,元素天生就唯一。
Set对象是值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会出现一次,即 Set 中的元素是唯一的。
那么就利用flat和Set实现一种最简单的解法吧。
[...new Set(arr.flat(Infinity))].sort((a, b) => a - b)
是不是最精简的答案了?利用flat,Set数据结构还有一些写法,可以参考上述链接的文章,自行理解。
我这里想说的是,我在上面看到的扁平化数组的方法:利用toString(),说出来之后,可能不值得一提,但是能够想到这个方法,我反正觉得挺厉害的。
这个方法是有一定的局限性的:数组元素只能是基本类型的数字或字符串,在这个面试题当中,当然是完美的解决方案之一。
arr.toString()
简单直接,不是吗?
那么扁平化之后,就是去重,和排序了。
但是这里将他扁平化成为字符串了,那么自然想到字符串当中有一个方法split,必须注意的是split之后的数组元素也是字符串,所以还需要将元素转换为数字。
arr.toString().split(",").map(Number)
当然这里转化为数字的方法也用到了ES6的方法:map。
如果想完全避免ES6, 就只剩下华山一条道了:for循环。既然都循环了,当然可以顺带做一下数组去重了,关于数组去重,我在前面写过两篇文章,这里不再赘述。这里利用的是hash去重的方法,正好可以对前面写的hash去重稍作优化。
// 1、扁平化数组 var flatArr = arr.toString().split(","); // 2、去重 var hash = {}; for (var i = 0, len = flatArr.length; i < len; i++) { hash[flatArr[i]] = "abc" } flatArr = []; // 3、将元素字符串转化为数字、遍历hash并不能保证输出顺序 for (var i in hash) { flatArr.push(+i) }
至于说将字符串转换为数字,是在for循环体内和去重一起做,还是去重之后,提取key值的时候再做,没有什么本质上的区别。我这里是在去重之后,提取hash对象的key值的时候,利用一元运算符+,进行的类型转换。
到这一步之后,就好办了,就只剩下排序了。排序的方法还是利用的数组方法sort。
那么整道题目的过程如下:
// 1、扁平化数组 var flatArr = arr.toString().split(","); // 2、去重 var hash = {}; for (var i = 0, len = flatArr.length; i < len; i++) { hash[flatArr[i]] = "abc" } flatArr = []; // 3、将元素字符串转化为数字、遍历hash并不能保证输出顺序 for (var i in hash) { flatArr.push(+i) } // 4、排序 flatArr = flatArr.sort(function(a, b) { return a - b })
此时,flatArr就是最后答案,进行了扁平化,去重,排序。