一道面试题引发的思考
面试题
前几天学员群里面在讨论面试题。题目如下,要求要用尽量少的代码进行处理尽量不要超过五行。
// 输入数据 const input = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10] // 输出数据 expect = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
其实这个就是一个比较基础的算法题。 需要处理扁平化、排序、去重三个问题,而且最好是能够利用函数式的写法这样代码就会简洁一些。
学霸答案
const ary = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10] console.log('ary', [... new Set(ary.flat(Infinity))].sort((a, b) => a - b))
解析一下:
- 扁平化使用ary的flat方法
- Set方式去重
- 排序sort常规操作
- 最后用...展开为数组 整个过程非常流畅,确实是学霸答案。感觉这些常用的函数运用的想自己的手脚一般自如。
扁平化的实现方法
1. flat函数
扁平化最简洁的方法就是flat
// depth代表展开深度默认值1 // Infinity为无限深度 const newArray = arr.flat([depth]);
2. 循环+递归 (5行)
const flatten = input => { result = [] input.forEach(v => Array.isArray(v) ? result = result.concat(flatten(v)) : result.push(v)) return result }
3. 归并方法:reduce
(1行 不过太难于理解了)
reduce的第二个参数:作为归并基础的初始值
const flatten = input => input.reduce((prev, next) => prev.concat(Array.isArray(next) ? flatten(next) : next), []);
4. ...
扩展运算符(ES6)
5行代码
const flatten = input => { while(input.some(v => Array.isArray(v))){ input = [].concat(...input) } return input }
5. toString法
一行代码
只适用于数组元素全部为数字的情况下
const flatten = ary => ary.toString().split(",").map(v => +v)
数组去重
1. 一般方法
const uniq = input => input.reduce((cur, next) => cur.indexOf(next) !== -1 ? cur : [...cur, next], [])
- 对象键值 + reduce 去重
速度最快, 占空间最多(空间换时间)
该方法执行的速度比其他任何方法都快, 就是占用的内存大一些。 现思路:新建一js对象以及新数组,遍历传入数组时,判断值是否为js对象的键, 不是的话给对象新增该键并放入新数组。 注意点:判断是否为js对象键时,会自动对传入的键执行“toString()”, 不同的键可能会被误认为一样,例如n[val]-- n[1]、n["1"]; 解决上述问题还是得调用“indexOf”。*/
const obj = {} const uniq = input => input.reduce((cur, next) => obj[next] ? cur : obj[next] = true && [...cur, next], [])
2. 排序相邻去重
一行搞定排序 + 去重
const uniq = input => input.sort((a, b) => a > b).reduce((cur, next) => cur[cur.length - 1] === next ? cur : [...cur, next], [])
3.数组下标法
const uniq = input => input.reduce((cur, next, i) => input.indexOf(next) !== i ? cur : [...cur, next], [])
4. Set去重
const uniq = input => [... new Set(input)]