数组扁平化就是将 [1, [2, [3]]] 这种多层的数组拍平成一层 [1, 2, 3]
实现数组扁平化的5种方法:
1、使用数组原型上的flat方法:
使用 Array.prototype.flat 可以直接将多层数组拍平成一层:
console.log([1, [2, [3]]].flat(2)) // [1, 2, 3] flat(2) 2是深度 无限深度:flat(Infinity)
2、递归遍历:
function flatten(arr) {
let newArr = [];
arr.forEach(value => {
if (Array.isArray(value)) {
newArr = newArr.concat(flatten(value));
} else {
newArr = newArr.concat(value);
}
})
return newArr;
}
let arr = [1, 2, 3, [4, 5], [6, [7, 8]],];
console.log(flatten(arr));
3、使用ES6的reduce函数:
function flatten(arr) {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flatten(cur) : cur)
}, []) //是数组就会递归调用这个方法,[1, [2, [3]]] => 1取出,[2, [3]] => 2取出,[3]
}
console.log(flatten([1,[2,[3]]]))
4、while循环结合some与扩展运算符:
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr
}
console.log(flatten([1,[2,[3]]]))
5、数组强制类型转换:
function flatten(arr){
return arr.toString().split(',').map(Number)
}
let arr = [1, 2, 3, [4, 5], [6, [7, 8]],];
console.log(flatten(arr));
实现数组去重的5种方法:
1、利用ES6的Set方法:
[...new Set(arr)]
// or
Array.from(new Set(arr)) //new Set(arr)结果不是一个数组,Array.from将它转换为数组
2、数组的includes方法:
function removeRepeat(arr) {
let newArr = [];
for (let i=0; i<arr.length; i++) {
//方法一
// if(newArr.indexOf(arr[i]) === -1){
// newArr.push(arr[i]);
// }
//方法二
if(!newArr.includes(arr[i])) {
newArr.push(arr[i]);
}
}
return newArr;
}
var arr = [8,11,20,5,20,8,0,2,4,0,8,19];
console.log(removeRepeat(arr));
3、利用ES6的filter方法:
function unique(arr) {
var res = arr.filter((item,index,array) => {
return array.indexOf(item) === index
})
return res
}
4、使用filter和Map:
function unique(arr) {
const map = new Map();
return arr.filter((item) => !map.has(item) && map.set(item));
}
var arr = [8,11,20,5,20,8,0,2,4,0,8,19];
console.log(unique(arr));
5、使用reduce:
let arr = [1,2,2,3,4,5,5,5]
let removeRepeat = arr.reduce((pre,cur) => {
if(!pre.includes(cur)){
return pre.concat(cur)
} else {
return pre
}
}, [])
console.log(removeRepeat);
排序算法:
稳定排序:冒插归基
不稳定排序:快选希堆
1、api sort()方法
const sort = (arr) => arr.sort((a, b) => a - b)
arr.sort((a,b) => a-b); //从小到大,对负数也行
arr.sort((a,b) => b-a); //sort()默认从小到大,此方法是从大到小
2、冒泡排序 时间复杂度O(n^2) 空间复杂度O(1)
function bubbleSort(arr) {
const len = arr.length-1
// 外层循环用于控制从头到尾的比较+交换到底有多少轮
for (let i = 0; i < len; i++) {
// 内层循环用于完成每一轮遍历过程中的重复比较+交换
for (let j = 0; j < len - i; j++) {
// 若相邻元素前面的数比后面的大
if (arr[j] > arr[j + 1]) {
// 利用es6数组解构赋值交换两者
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
}
return arr
}
3、快速排序 时间复杂度O(nlogn) 空间复杂度O(logn)
const quickSort = function (arr) {
if (arr.length <= 1) return arr ///如果数组<=1,则直接返回,也是递归出口
let pivotIndex = Math.floor(arr.length / 2) //Math.floor()可以获得一个数的整数部分,而不是四舍五入
//找基准,并把基准从原数组删除
let pivot = arr.splice(pivotIndex, 1)[0]
let left = [], right = [] //定义左右数组
for (let i = 0; i < arr.length; i++) { //比基准小的放在left,比基准大的放在right
if (arr[i] < pivot) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
// 不断重复第一步和第二步,直到所有子集只剩下一个元素为止
return quickSort(left).concat(pivot, quickSort(right))
}
快排-双指针法
function quickSort(arr, low, high) {
let key = arr[low], start = low, end = high
while (end > start) {
while (end > start && arr[end] >= key) end-- //移动右指针
if (arr[end] <= key) {
[arr[end], arr[start]] = [arr[start], arr[end]]
}
while (end > start && arr[start] <= key) start++ //移动左指针
if (arr[start] >= key) {
[arr[start], arr[end]] = [arr[end], arr[start]]
}
}
if (start > low) quickSort(arr, low, start - 1) //左边递归
if (end < high) quickSort(arr, end + 1, high) //右边递归
return arr
}
console.log(quickSort([4, 2, 1, 5, 3, 2], 0, 5)) //[ 1, 2, 2, 3, 4, 5 ]
4、插入排序 时间复杂度O(n^2) 空间复杂度O(1)
function insertSort(arr) {
const handle = [arr[0]], len = arr.length
for (let i = 1; i <= len - 1; i++) {
const current = arr[i]
for (let j = handle.length - 1; j >= 0; j--) {
if (current > handle[j]) {
handle.splice(j + 1, 0, current)
break
}
if (j === 0) {
handle.unshift(current)
}
}
}
return handle
}
插入排序-优化版
// 将arr[]按升序排列
function insertSort(arr) {
for (let i = 1; i < arr.length; i++) {
//将arr[i]插入到arr[i-1],arr[i-2],arr[i-3]……之中
for (let j = i; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
[arr[j - 1], arr[j]] = [arr[j], arr[j - 1]]
}
}
}
return arr
}
5、选择排序 时间复杂度O(n^2) 空间复杂度O(1)
// 第一个开始和一组中最小的交换,往后类推
function selectSort(arr) {
const len = arr.length
// 定义 minIndex,缓存当前区间最小值的索引,注意是索引
let minIndex
for (let i = 0; i < len - 1; i++) {
// 初始化 minIndex 为当前区间第一个元素
minIndex = i
// i、j分别定义当前区间的上下界,i是左边界,j是右边界
for (let j = i + 1; j < len; j++) {
// 若 j 处的数据项比当前最小值还要小,则更新最小值索引为 j
if (arr[minIndex] > arr[j]) {
minIndex = j
}
}
// 如果 minIndex 对应元素不是目前的头部元素,则交换两者
if (minIndex !== i) {
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]
}
}
return arr
}
管道函数
题目:
实现一个函数可以实现 数组扁平化和去重并排好序
一把嗦写法:
// 扁平+去重+排序
const fn = (arr) => {
let arr2 = arr.flat(Infinity)
let arr3 = [...new Set(arr2)]
return arr3.sort((a, b) => a - b)
}
let arr = [[12, 2, 2], [6, 7, 8, 5], [3, 4, 5, 9, [10, 3, [1, 7, [11]]]]]
console.log(fn(arr))
这样子写的话, 不利于代码复用, 我们尽可能让一个函数只做一件事情, 所以可以将这个函数拆成三个函数, 然后再利用一个辅助函数让它依次执行
管道函数写法:
// 扁平
const flatten = (arr) =>
arr.reduce((acc, v) => acc.concat(Array.isArray(v) ? flatten(v) : v), [])
// 去重
const unique = (arr) => [...new Set(arr)]
// 排序
const sort = (arr) => arr.sort((a, b) => a - b)
// 管道函数
const pipe = (...fns) =>
fns.reduce((f, g) =>
(...args) =>
g(f(...args))
)
console.log(pipe(flatten, unique, sort)(arr))
完结~