1.数组扁平化
数组扁平化是指将一个多维数组变为一维数组
[1, [2, 3, [4, 5]]] ------> [1, 2, 3, 4, 5]
核心:遍历数组arr,若arr[i]为数组则递归遍历,直至arr[i]不为数组并与之前的结果concat。
扁平化嵌套数组:
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
//使用 Infinity 作为深度,展开任意深度的嵌套数组
arr3.flat(Infinity);
// [1, 2, 3, 4, 5, 6]
扁平化与空项:
flat()
方法会移除数组中的空项:
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]
(1)reduce
reduce是一种数组的方法,它接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce包含两个参数:回调函数,传给total的初始值
//求数组的各项值的相加的和:
arr.reduce((total,item)=>{ //total为之前的计算结果,item为数组的各项直
return total+item;
},0);
遍历数组的每一项,若值为数组则递归遍历,否则concat。
function flatten(arr){
return arr.reduce((result,item)=>{
return result.concat(Array.isArray(item)?flatten(item):item);
},[]);
}
(2) to String & split
调用数组的toString方法,将数组变为字符串再用split分割还原成数组
function flatten(arr){
return arr.toString().split(',').map(function(item){
return Number(item);
})
}
split分割形成的数组的每一项为字符串,所以需要用一个map方法遍历数组将其每一项转换为数值型
(3) join & split
和上面的toString一样,join也可以将数组转换为字符串
function faltten(arr){
return arr.join(',').split(',').map(function(item){
return parseInt(item);
})
}
(4) 递归
递归遍历每一项,若为数组则继续遍历,否则concat
function flatten(arr){
var res =[];
arr.map(item=>{
if(Array.isArray(item)){
res = res.concat(flatten(item));
}else{
res.push(item);
}
});
return res;
}
(5)扩展运算符
es6的扩展运算符能将二维数组变为一维
[].concat(...[1, 2, 3, [4, 5]]); // [1, 2, 3, 4, 5]
根据这个结果我们可以做一个遍历,若arr中含有数组则使用一次扩展运算符,直至没有为止。
function flatten(arr){
while(arr.some(item=>Array.isArray(item))){
arr = [].concat(...arr);
}
return arr;
}
js嵌套数组的展开:
实现一个嵌套数组的flat方法,展开深度为可根据参数设定展开深度,效果如下:
var arr = [1,2,[3,4],[5,[6,7]]]
var flatArr = flat(arr,1)
console.log(flatArr)
//展开结果:[1,2,3,4,5,[6,7]]
function flat(arr,deepth){
newArr = [];
deepth--;
arr.forEach(v=>{
if(v instanceof Array){
newArr.push(...v);
}else{
newArr.push(v);
}
})
if(deepth>0)
flat(newArr,deepth);
return newArr;
}
var arr = [1, 2, [3, 4],
[5, [6, 7,[8,9,10]]]
]
var flatArr = flat(arr, 2)
console.log(flatArr)
//使用reduce、concat和递归无限反嵌套多层嵌套的数组
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
function flattenDeep(arr1){
return arr1.reduce((acc,val)=>Array.isArray(val)?acc.concat(flattenDeep(val)):acc.concat(val),[]);
}
flattenDeep(arr1);
// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
// 不使用递归,使用 stack 无限反嵌套多层嵌套数组
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
function flatten(input){
var res = [];
var stack = [...input];
while(stack.length){
// 使用 pop 从 stack 中取出并移除值
var next = stack.pop();
if(Array.isArray(next)){
// 使用 push 送回内层数组中的元素,不会改动原始输入 original input
stack.push(...next);
}else{
res.push(next);
}
}
// 使用 reverse 恢复原数组的顺序
res.reverse();
return res;
}
flatten(arr1);
2.数组去重
(1)for循环嵌套,利用splice去重
function newArr(arr){
for(var i=0; i<arr.length;i++){
for(var j=i+1; j<arr.length;j++){
if(arr[i]==arr[j]){
//如果第一个等于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
var arr = [1,1,2,5,6,3,5,5,6,8,9,8];
console.log(newArr(arr));
(2)新建数组,利用indexOf去重
方法“indexOf”是es5的方法,IE8以下不支持,基本思路是新建一个数组,原数组遍历传入新数组,判断值是否存在,值不存在就加入该新数组中。
function newArr(array){
//一个新的数组
var arr = [];
for(var i=0;i<arr.length;i++){
if(arr.indexOf(array[i])==-1){
arr.push(array[i]);
}
}
return arr;
}
var arr = [1,1,2,5,5,6,8,9,8];
console.log(newArr(arr))
(3) ES6中利用Set去重
function newArr(arr){
return Array.from(new Set(arr));
}
var arr = [1,1,2,9,6,9,6,3,1,4,5];
console.log(newArr(arr))
补充: js中set方法
Set
和Map
类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。
var s = new Set([1,2,3,'3',4]);
//添加一个key
s.add(5);
//重复元素在Set中自动被过滤
s.add(5);
console.log(s);//Set {1, 2, 3, 4,5}
//删除一个key
s.delete(2);
console.log(s);//Set{1, 3, "3", 4, 5}//注意数字3和字符串'3'是不同的元素。