js数组相关的面试题, 熬夜整理

680 阅读3分钟

1.jpeg

1.判断是否为数组的几种方法

  • instanceof instanceof运算符用于检验构造函数的prototype属性是否出现在对象的原型链中的任何位置,返回一个布尔值
let arr = []
console.log(arr instanceof Array); // true
  • constructor 实例的构造函数属性constructor指向构造函数,通过constructor属性可以判断是否为一个数组
let arr = []
console.log(arr.constructor === Array);//true
  • Object.prototype.toString Object.prototype.toString.call()可以获取到对象的不同类型
let arr = []
console.log(Object.prototype.toString.call(arr));//[object Array]
  • Array.isArray() Array.isArray()用于确定传递的值是否是一个数组,返回一个布尔值
let arr = []
console.log(Array.isArray(arr));//true

constructor 和 prototype 有可能会被改写,所以 instanceof 和 constructor判断不一定准确

2.数组分割

const listChunk = (list = [], chunkSize = 1) => {
  const result = [];
  const tmp = [...list];
  if (!Array.isArray(list) || !Number.isInteger(chunkSize) || chunkSize <= 0) {
      return result;
  };
  while (tmp.length) {
      result.push(tmp.splice(0, chunkSize));
  };
  return result;
};

console.log(listChunk(['a', 'b', 'c', 'd']));// [['a'], ['b'], ['c'], ['d']]

console.log(listChunk(['a', 'b', 'c', 'd', 'e'], 2));// [['a', 'b'], ['c', 'd'], ['e']]

console.log(listChunk(['a', 'b', 'c', 'd'], 0));// []

console.log(listChunk(['a', 'b', 'c', 'd'], -1));// []

3.数组去重

  • 利用ES6的Set
/** Set中不允许出现重复的元素 */
let arr1 = [1,2,3,1,3,4]
let arr2 = Array.from(new Set(arr1))
console.log(arr2); // [ 1, 2, 3, 4 ]
  • 利用ES6的Map
/** 创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。
    由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果
*/
let arr = [1, 0, 2, 3, 1, 0, 4]
function unique(arr) {
     let map = new Map();
     let arr1 = []
     for (let i = 0, len = arr.length; i < len; i++) {
          if (map.has(arr[i])) {      // 判断是否存在该key值
              map.set(arr[i], true);
          }
          else {
              map.set(arr[i], false);
              arr1.push(arr[i]);
          }
      }
    return arr1;
}
console.log(unique(arr)); // 1, 0, 8, 3, -9, 7
  • 利用reduce去重
let arr = [1, 2, 3, 4, 3, 2, 4]
let myArray = arr.reduce(function (accumulator, currentValue) {
  if (accumulator.indexOf(currentValue) === -1) {
    accumulator.push(currentValue)
  }
  return accumulator
}, [])

console.log(myArray) //[ 1, 2, 3, 4 ]
  • 在原数组上去重
let arr = [1, 2, 0, 3, 1, 3]
const removeDuplicates = (nums) => {
  let len = nums.length - 1
  // 从后向前遍历数组,indexOf从前向后找索引。
  for(let i = len; i>=0; i--) {
      if(nums.indexOf(nums[i]) != i) {
          nums[i] = nums[len--]
      }
  }
  // 删除重复项
  nums.splice(len+1)
  return nums
}
// 测试
removeDuplicates(arr)
console.log(arr); //[ 1, 2, 0, 3 ]

4.数组扁平化

let arr = [1, 2, [3, 4], [5, [6, 7]], 8];
// 第一种方法:
console.log(arr.flat(Infinity)); // [1, 2, 3, 4, 5, 6, 7, 8]

// 第二种方法:
console.log(arr.toString().split(',')); // [1, 2, 3, 4, 5, 6, 7, 8]

// 第三种方法:
function flatten(arr) {
    return arr.reduce((prev, item) => {
        return prev.concat(Array.isArray(item) ? flatten(item) : item);
    }, [])
}
console.log(flatten(arr)); // [1, 2, 3, 4, 5, 6, 7, 8]

// 第四种方法:(对象数组举例)
const arr = [
  {
    id: 1,
    children: [
      {
        id: 11,
        children: [
          {
            id: 111,
          },
        ],
      },
      {
        id: 12,
        children: [
          {
            id: 112,
          },
        ],
      },
    ],
  },
  {
    id: 2,
    children: [
      {
        id: 21,
      },
      {
        id: 22,
      },
    ],
  },
];

function flatten(arr) {
  return [].concat(
    ...arr.map((item) => [].concat(item, ...flatten(item.children || [])))
  );
}

console.log(flatten(arr));
//输出如下:

6d3dfe8edfd5e6ce3afc333cfb5b46b.png

5.数组柯里化Curry(求和)

function sum(){
  var arr = [].slice.apply(arguments);
  var fn = function(){
      arr = arr.concat([].slice.apply(arguments))
      return fn;
  }
  fn.sumOf = function(){
      return  arr.reduce((total,num)=>total+num,0);
  }
  return fn;
}
console.log(sum(1,3).sumOf()) // 4
console.log(sum(1,2)(3,4).sumOf())// 10

6.数组乱序

//第一种方法
function arrScrambling(arr) {
  for (let i = 0; i < arr.length; i++) {
    const randomIndex = Math.round(Math.random() * (arr.length - 1 - i)) + i;
    [arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]];
  }
  return arr;
}
console.log(arrScrambling([1,2,3,4])) // [1, 4, 2, 3]

//第二种方法
const shuffleArray = (arr) => arr.sort(() => 0.5 - Math.random());
console.log(shuffleArray([1, 2, 3, 4])); // [1, 2, 4, 3]

7.计算数组中每个元素出现的次数

let charArray = ['a', 'b', 'c', 'a', 'c'];
let charObject = charArray.reduce(function (allchars, char) {
  if (char in allchars) {
    allchars[char]++;
  } else {
    allchars[char] = 1;
  }
  return allchars;
}, {});
console.log(charObject); // { a: 2, b: 1, c: 2 }

8.实现数组的map方法

//循环实现
const myMap = function(fn, context) {
    let arr = Array.prototype.slice.call(this)
    let mapArr = Array()
    //避免稀疏
    const temArr = Reflect.ownKeys(arr)
    //删除length
    temArr.pop()
    for (let i of temArr) {
        console.log('i', i);
       mapArr[i] = fn.call(context, arr[i], i, this)
      }
      return mapArr
    }
    Array.prototype.myMap = myMap
    console.log([1,2,3].myMap(number => number + 1)) //[ 2, 3, 4 ]

//利用reduce实现
Array.prototype.reduceMap = function(fn, context) {
    let arr = Array.prototype.slice.call(this)
    return arr.reduce((pre, cur, index) => {
        return [...pre, fn.call(context, cur, index, this)]
    }, [])
}
console.log([1,2,3].reduceMap(number => number + 1)); //[ 2, 3, 4 ]

9.实现数组的reduce方法

Array.prototype.myReduce = function(fn, initValue) {
    let arr = Array.prototype.slice.call(this)
    let res, startIndex = 0
    // if (!initValue) {
    //     // 找到第一个非空的元素和下标
    //     for (let index = 0; index < arr.length; index++) {
    //         if(!arr.hasOwnProperty(index)) continue
    //         res = arr[index];
    //         startIndex = index
    //         break
    //     }
    // } else {
    //     res = initValue
    // }
    // for (let index = ++startIndex; index < arr.length; index++) {
    //     if(!arr.hasOwnProperty(index)) continue
    //     res = fn.call(null, res, arr[index], index, this)   
    // }
    // return res

    //避免稀疏数组, 删除length
    let tempArr
    (tempArr = Reflect.ownKeys(arr)).pop()
    if (initValue) {
        res = initValue
    } else {
        res = arr[tempArr[0]]
        tempArr.shift()
    }
    for (const i of tempArr) {
        res = fn.call(null, res, arr[i], i, this) 
    }
    return res
}
console.log([2,4,6, ,8].myReduce((pre, cur) => pre + cur, 1)); // 21

10.去除数组中的无效值

创建一个新数组,包含原数组中所有的非假值元素。例如falsenull,0""undefined, 和 NaN 都是被认为是“假值”。

const compact = arr => arr.filter(Boolean)
console.log(compact([0, 1, false, true, 2, '', 3]));//[ 1, true, 2, 3 ]

11.数组中最大值

const max = arr => Math.max(...arr.filter(v => Boolean(v) || v === 0))

12.对象数组去重

const uniqueBy = (arr, key) => {
    return arr.reduce((acc, cur) => {
        const ids = acc.map(item => item[key])
        return ids.includes(cur[key]) ? acc : [...acc, cur]
    }, [])
}
const responseList = [
    { id: 1, a: 1 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
    { id: 2, a: 2 }
]
console.log(uniqueBy(responseList, 'id'));
//[ { id: 1, a: 1 }, { id: 2, a: 2 }, { id: 3, a: 3 } ]