一.数组去重
1. hash
function unique(array){
let hash={}
let result=[]
for(let i=0;i<array.length;i++){
if(!hash[array[i]]){
result.push(array[i])
hash[array[i]]=true
}
}
return result
}
2. set
function unique(array){
return Array.from(new Set(array))//array放Set就会变成没有重复元素的集合
}
//WeakMap
function unique(arr) {
const map = new Map();
return arr.filter((a) => !res.has(a) && res.set(a, 1))
}
二. 数组扁平化
把多层嵌套的数组展成一维数组
1. arr.flat()
直接使用数组上的方法。flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
var newArray = arr.flat([depth])
depth是可选的,默认是1.指定可以展开的嵌套数组的深度。
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,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2. for循环
var arr1 = [1, 2, 3, [1, 2, 3, 4, [2, 3, 4]]];
function flatten(arr) {
var res = [];
for (let i = 0, length = arr.length; i < length; i++) {
if (Array.isArray(arr[i])) {
res = res.concat(flatten(arr[i])); //concat 并不会改变原数组
//res.push(...flatten(arr[i])); //扩展运算符
} else {
res.push(arr[i]);
}
}
return res;
}
flatten(arr1); //[1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
3. reduce + 递归
var arr = [1, [2, [3, 4]]];
function flatten(arr) {
return arr.reduce(function(result, item){
return result.concat(Array.isArray(item) ? flatten(item) : item)
}, [])
}
三.斐波那契数列
//动态规划
var fib = function(n) {
let a = 0,b = 1,sum = 0;
if(n === 1) return 1;
for(let i = 0;i<n-1;i++) {
sum = (a + b)% 1000000007;
a = b;
b = sum;
}
return sum;
};
//递归
const fib = function(n) {
const dp = [0, 1];
for (let i = 2; i <= n; i++) {
dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007;
}
return dp[n];
};
四.数组乱序
具体思路:遍历整个数组,从最后一个位置开始,把它和一个任意位置的元素交换,这个任意位置是随机生成的,也包括最后一个位置。交换完以后,再交换倒数第二个元素,从包括它的其余元素里随机一个位置。
function shuffle(arr){
for(let i=arr.length-1;i>=0;i--){
var j=Math.floor(Math.random()*(i+1))
var temp=arr[j]
arr[j]=arr[i]
arr[i]=temp
}
return arr
}
五.把数组按父子关系转换成树型结构
const list = [
{id: 1, name: 'A', parentId: 0},
{id: 2, name: 'B', parentId: 0},
{id: 3, name: 'C', parentId: 1},
{id: 4, name: 'D', parentId: 1},
{id: 5, name: 'E', parentId: 2},
{id: 6, name: 'F', parentId: 3},
{id: 7, name: 'G', parentId: 2},
{id: 8, name: 'H', parentId: 4},
{id: 9, name: 'I', parentId: 5}
];
//转换成下面的形式
//const tree = [
// {
// id: 1,
// name: 'A',
// parentId: 0,
// children: [
// {
// id: 3,
// name: 'C',
// parentId: 1,
// children: [...]
// }
// ]
// },
// ...
//
paerntId是0的对象,是最上层的。用children属性表示它的孩子。孩子再嵌套孩子。
function toTree(list){
list.forEach(item=>{
let parentId=item.parentId
if(parentId!==0){
list.forEach(el=>{
if(el.id===parentId){
if(!el.children){
el.children=[]
}
el.children.push(item)
}
})
}
})
list.filter(el=>el.parentId===0)
return list
}
双重循环,先遍历所有项,parentId是0的什么也不做,不是0的,就说明它是某个项的孩子,就先拿到它的parentId,然后再遍历所有项,找到它的parent,放进children数组里。遍历完之后,parentId是0的项,里边的children数组就保存了所有父子结构,其余不是0的就可以去掉了。因为放进children数组里的是对象,是引用类型,所以如果2是1的孩子,3又是2的孩子,3被放进了2的children里,这个链的结构也都保存在了1的children里。
六. 改变原数组和不改变原数组的方法整理
改变原数组:
pop() : 删除 arrayObject 的最后一个元素,把数组长度减 1,并且返回它删除的元素的值。如果数组已经为空,则 pop() 不 改变数组,并返回 undefined 值。arrayObject.pop()
push() : push() 方法可把它的参数顺序添加到 arrayObject 的尾部。它直接修改 arrayObject,而不是创建一个新的数组, arrayObject.push(newelement1,newelement2,….,newelementX)
reverse() : 该方法会改变原来的数组,而不会创建新的数组。arrayObject.reverse()
shift() : 数组的第一个元素从其中删除,并返回第一个元素的值,如果数组是空的,那么 shift() 方法将不进行任何操作。
unshift() : unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。arrayObject.unshift(newelement1,newelement2,….,newelementX)返回arrayObject 的新长度
sort() : 对数组的引用。请注意,数组在原数组上进行排序,不生成副本。arrayObject.sort(sortby) (如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
-
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
-
若 a 等于 b,则返回 0。
-
若 a 大于 b,则返回一个大于 0 的值。
splice() : splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。
如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组
arrayObject.splice(index,howmany,item1,…..,itemX)
不改变原数组:
concat():用于连接两个或多个数组,仅会返回被连接数组的一个副本,arrayObject.concat(arrayX,arrayX,……,arrayX)
join() :返回一个字符串。该字符串是通过把 arrayObject 的每个元素转换为字符串,然后把这些字符串连接起来, arrayObject.join(separator)
slice() :如果数组是空的 arrayObject.slice(start,end)
七.once函数,传入函数参数只执行一次
function ones(func){
var tag=true;
return function(){
if(tag==true){
func.apply(null,arguments);
tag=false;
}
return undefined
}
}