数组的扁平化和去重

1,067 阅读3分钟

t1.jpg

前言

数组的扁平化和去重是面试里面出现频率比较高的两个,所以我们需要重视起来。
本文章是基于死磕36个手写题 写出来的,感兴趣的可以去看一下呀!

数组去重

前端的更新是很快的,所以每一个问题都是有很多的解法,我们需要接受新的东西,但是也不能放过旧的东西。
像数组去重,es5的解法和es6的解法就完全不同,虽然ES6的解法要简单的很多,但是es5的解法我们也要了解呀!

废话不多说,先上代码!

ES5实现:

function unique(arr) {
    var res = arr.filter(function(item, index, array) {
        return array.indexOf(item) === index
    })
    return res
}
console.log(unique([1,2,2,3,4,55,55])) //[1,2,3,55]
  1. filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

  2. indexOf() 方法可返回数组中某个指定的元素位置。

该方法将从头到尾地检索数组,看它是否含有对应的元素。开始检索的位置在数组 start 处或数组的开头(没有指定 start 参数时)。如果找到一个 item,则返回 item 的第一次出现的位置。开始位置的索引为 0。

如果在数组中没找到指定元素则返回 -1。

提示:如果你想查找字符串最后出现的位置,请使用 lastIndexOf() 方法。

ES6实现:

var unique = arr => [...new Set(arr)]
console.log(unique([1,2,2,3,4,55,55])) //[1,2,3,55]
  1. ...是扩展运算符(对象展开符)
    扩展运算符( spread )是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

扩展

扩展运算符不仅可以数组去重,还可以合并数组

let a=[1,2,3]
let b=[2,3,4]
let c=[...a,...b]
console.log(c) // [1,2,3,2,3,4]
var unique = arr => [...new Set(arr)]
console.log(unique(c))//[1,2,3,4]

数组扁平化

数组扁平化就是将 [1, [2, [3]]] 这种多层的数组拍平成一层 [1, 2, 3]。使用 Array.prototype.flat 可以直接将多层数组拍平成一层:

[1, [2, [3]]].flat(2)  // [1, 2, 3]
  1. Array.prototype.flat() 用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。

  2. 不传参数时,默认“拉平”一层,可以传入一个整数,表示想要“拉平”的层数。 传入 <=0 的整数将返回原数组,不“拉平”

  3. Infinity 关键字作为参数时,无论多少层嵌套,都会转为一维数组

  4. 如果原数组有空位,Array.prototype.flat() 会跳过空位。

ES5实现:递归。

上代码!上代码!

function flatten(arr) {
    var result = [];
    for (var i = 0, len = arr.length; i < len; i++) {
        if (Array.isArray(arr[i])) {
            result = result.concat(flatten(arr[i]))
        } else {
            result.push(arr[i])
        }
    }
    return result;
}

flatten 是基于lodash的一种方法。而且lodash中的 flatten 和 flattenDeep 方法都可以实现数组的扁平化。 什么是lodash? Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。

Lodash 遵循 MIT 开源协议发布,并且支持最新的运行环境。 查看各个构件版本的区别并选择一个适合你的版本。

为什么选择 Lodash ?

Lodash 通过降低 array、number、objects、string 等等的使用难度从而让 JavaScript 变得更简单。 Lodash 的模块化方法 非常适用于:

遍历 array、object 和 string

对值进行操作和检测

创建符合功能的函数

通过扩展运算符确实可以避免递归,但是却要使用到循环,如果数组层级过高,循环的消耗也不小,如果连循环也不用呢?

使用字符串,利用正则去掉中括号,实现最简单,而且消耗也最小:

//扁平化数组(不使用循环,使用字符串)
function flatten(arr) {
    let str = JSON.stringify(arr).replace(/\[|\]/g, '');
    return JSON.parse(Array.of('[' + str + ']')[0]);
}

其实如果没有极端数据的话,使用toString()然后拆分组合也可以实现扁平化,但是不完美,比如以下数据:

let arr = [2, [3.2, [’s,d,w’],’a,b,c,d,e’]]; 
arr.toString() ==> “2,3.2,s,d,w,a,b,c,d,e” 

ES6实现:

function flatten(arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr);
    }
    return arr;
}

递归其实是存在性能消耗的问题,每次都要重新创建函数,如果不用递归是不是也可以实现呢?
所以ES6就加上了展开运算符 扩展运算符,可以展开数组,每次扒开一层,通过循环可以实现数组扁平化。

总结

数组去重还有数组扁平化我能介绍的也就这么多了,当然还有很多不足点需要我去学习,所以我会继续努力的,欢迎大家多多指教。