总结XVII-数组操作常用代码

236 阅读4分钟

一.数组去重

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))//arraySet就会变成没有重复元素的集合
}
//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
    }
}