数组相关手写代码题

156 阅读2分钟

多维数组降维

基础写法:需要额外变量 递归

var result=[]
var flat=function (arr) {
  for(let i=0;i<arr.length;i++){
    if(Array.isArray(arr[i])){
      flat(arr[i])
    }else{
      result.push(arr[i]);
    }
  }
}

var list=[1,2,[[3,4,5],6],[7,8],[9]];
flat(list);
console.log(result) //[1,2,3,4,5,6,7,8,9]

函数式写法(推荐):

var flat=function (arr) {
  var result=[]
  for(let i=0;i<arr.length;i++){
    if(Array.isArray(arr[i])){
      result=result.concat(flat(arr[i]))
    }else{
      result.push(arr[i]);
    }
  }
  return result;
}
var list=[1,2,[[3,4,5],6],[7,8],[9]];
console.log(flat(list))
//延伸:将改方法绑定到数组的原型链上,arr换成this
Array.prototype.flatten=function () {
  var result=[]
  for(let i=0;i<this.length;i++){
    if(Array.isArray(this[i])){
      result=result.concat(this[i].flatten())
    }else{
      result.push(this[i]);
    }
  }
  return result;
}

字符串式写法

var flat=function(arr){
  let strarr=arr+"";
  let str=strarr.split(",");
  return str;
}

究极写法:

let flatten = arr => arr.reduce((begin,current)=>{
  Array.isArray(current)?begin.push(...flatten(current)):begin.push(current);
  return begin
},[])

数组去重的五种方法:

  1. Array.filter() + indexOf
function deRepeat1(nums) {
    let res=[]
    res=nums.filter((item,index)=>{
        return nums.indexOf(item)===index
    })
    return res;
}
  1. for...of + includes()
function deRepeat2(nums) {
    let res=[]
    for(let item of nums){
        !res.includes(item)&&res.push(item)
    }
    return res;
}
  1. 双重 for 循环
function deRepeat3(nums) {
    let res=[]
    for(let i=0;i<nums.length;i++){
        for(let j=0;j<nums.length;j++){
            if(nums[j]==nums[i]&&i==j){
                res.push(nums[i])
                break;
            }
        }
    }
    return res;
}
  1. Array.sort()
function deRepeat4(nums) {
    let res=[]
    let arr=nums.sort()
    for(let i=0;i<arr.length-1;i++){
        if(arr[i]!==arr[i+1]) res.push(arr[i])
    }
    res.push(arr[arr.length-1])
    return res;
}
  1. for...of + Object (推荐)
function deRepeat5(nums) {
    let res=[]
    let obj={}
    for(let item of nums){
        if(!obj[item]){
            res.push(item);
            obj[item]=1;
        }
    }
    return res;
}
  1. ES6的new Set() (推荐)
function deRepeat6(nums) {
    return Array.from(new Set([...nums]));
}

实现数组原型方法

forEach

Array.prototype.forEach2 = function(callback, thisArg) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)  // this 就是当前的数组
    const len = O.length >>> 0  // 后面有解释
    let k = 0
    while (k < len) {
        if (k in O) {
            callback.call(thisArg, O[k], k, O);
        }
        k++;
    }
}

O.length >>> 0 是什么操作?就是无符号右移 0 位,那有什么意义嘛?就是为了保证转换后的值为正整数。其实底层做了 2 层转换,第一是非 number 转成 number 类型,第二是将 number 转成 Uint32 类型

map

Array.prototype.map2 = function(callback, thisArg) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)
    const len = O.length >>> 0
    let k = 0, res = []
    while (k < len) {
        if (k in O) {
           res[k] = callback.call(thisArg, O[k], k, O);
        }
        k++;
    }
    return res
}

filter

Array.prototype.filter2 = function(callback, thisArg) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)
    const len = O.length >>> 0
    let k = 0, res = []
    while (k < len) {
        if (k in O) {
           if (callback.call(thisArg, O[k], k, O)) {
               res.push(O[k])                
           }
        }
        k++;
    }
    return res
}

some

Array.prototype.some2 = function(callback, thisArg) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)
    const len = O.length >>> 0
    let k = 0
    while (k < len) {
        if (k in O) {
           if (callback.call(thisArg, O[k], k, O)) {
               return true
           }
        }
        k++;
    }
    return false
}

reduce

Array.prototype.reduce2 = function(callback, initialValue) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)
    const len = O.length >>> 0
    let k = 0, acc
    if (arguments.length > 1) {
        acc = initialValue
    } else {
        // 没传入初始值的时候,取数组中第一个非 empty 的值为初始值
        while (k < len && !(k in O)) {
            k++
        }
        if (k > len) {
            throw new TypeError( 'Reduce of empty array with no initial value' );
        }
        acc = O[k++]
    }
    while (k < len) {
        if (k in O) {
            acc = callback(acc, O[k], k, O)
        }
        k++
    }
    return acc
}

深拷贝浅拷贝

JSON方法实现

//深拷贝
JSON.stringify() & JSON.parse()
//缺点:拷贝对象包含正则,函数,或者undefined时会失效
let obj = { a: 1, b: { x: 3 } };
// let obj2 = JSON.parse(JSON.stringify());

递归实现

function deepClone(obj) {
  let res = obj instanceof Array ? [] : {};
  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      res[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
    }
  }
  return res;
}

多维数组每一维排列组合

var result = [];
var results = [];
var doExchange = function (arr, depth) {
  for (let i = 0; i < arr[depth].length; i++) {
    result[depth] = arr[depth][i];
    if (depth !== arr.length - 1) {
      doExchange(arr, depth + 1);
    } else {
      results.push(result.join("").split(""));
    }
  }
};
doExchange([[1, 2, 3],[4, 5],[6, 7]],0);
// [ 1, 4, 6 ],
// [ 1, 4, 7 ],
// [ 1, 5, 6 ],
// [ 1, 5, 7 ],
// [ 2, 4, 6 ],
// [ 2, 4, 7 ],
// [ 2, 5, 6 ],
// [ 2, 5, 7 ],
// [ 3, 4, 6 ],
// [ 3, 4, 7 ],
// [ 3, 5, 6 ],
// [ 3, 5, 7 ]