大厂前端面试常问的数据处理,必会系列(一)

100 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

  • 实现日期格式化函数
  • 交换a,b的值,不能使用临时变量
  • 实现数组的乱序输出
  • 实现数组元素求和
  • 实现数组的扁平化(重要)

1. 实现日期格式化函数

输入:

 dateFormat(new Date('2020-12-01'), 'yyyy/MM/dd') // 2020/12/01
 dateFormat(new Date('2020-04-01'), 'yyyy/MM/dd') // 2020/04/01
 dateFormat(new Date('2020-04-01'), 'yyyy年MM月dd日') // 2020年04月01日
 const dateFormat = (dateInput, format)=>{
     var day = dateInput.getDate() 
     var month = dateInput.getMonth() + 1  
     var year = dateInput.getFullYear()   
     format = format.replace(/yyyy/, year)
     format = format.replace(/MM/,month)
     format = format.replace(/dd/,day)
     return format
 }

2. 交换a,b的值,不能用临时变量

巧妙的利用两个数的和、差:

 a = a + b
 b = a - b
 a = a - b

3. 实现数组的乱序输出

主要的实现思路就是:

  • 取出数组的第一个元素,随机产生一个索引值,将该第一个元素和这个索引对应的元素进行交换。
  • 第二次取出数据数组第二个元素,随机产生一个除了索引为1的之外的索引值,并将第二个元素与该索引值对应的元素进行交换
  • 按照上面的规律执行,直到遍历完成
 var arr = [1,2,3,4,5,6,7,8,9,10];
 for (var 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]];
 }
 console.log(arr)

还有一方法就是倒序遍历:

 var arr = [1,2,3,4,5,6,7,8,9,10];
 let length = arr.length,
     randomIndex,
     temp;
   while (length) {
     randomIndex = Math.floor(Math.random() * length--);
     temp = arr[length];
     arr[length] = arr[randomIndex];
     arr[randomIndex] = temp;
   }
 console.log(arr)

4. 实现数组元素求和

  • arr=[1,2,3,4,5,6,7,8,9,10],求和
 let arr=[1,2,3,4,5,6,7,8,9,10]
 let sum = arr.reduce( (total,i) => total += i,0);
 console.log(sum);
  • arr=[1,2,3,[[4,5],6],7,8,9],求和
 var = arr=[1,2,3,[[4,5],6],7,8,9]
 let arr= arr.toString().split(',').reduce( (total,i) => total += Number(i),0);
 console.log(arr);

递归实现:

 let arr = [1, 2, 3, 4, 5, 6] 
 ​
 function add(arr) {
     if (arr.length == 1) return arr[0] 
     return arr[0] + add(arr.slice(1)) 
 }
 console.log(add(arr)) // 21

5. 实现数组的扁平化

(1)递归实现

普通的递归思路很容易理解,就是通过循环递归的方式,一项一项地去遍历,如果每一项还是一个数组,那么就继续往下遍历,利用递归程序的方法,来实现数组的每一项的连接:

 let arr = [1, [2, [3, 4, 5]]];
 function flatten(arr) {
   let result = [];
 ​
   for(let i = 0; i < arr.length; i++) {
     if(Array.isArray(arr[i])) {
       result = result.concat(flatten(arr[i]));
     } else {
       result.push(arr[i]);
     }
   }
   return result;
 }
 flatten(arr);  //  [1, 2, 3, 4,5]

(2)reduce 函数迭代

从上面普通的递归函数中可以看出,其实就是对数组的每一项进行处理,那么其实也可以用reduce 来实现数组的拼接,从而简化第一种方法的代码,改造后的代码如下所示:

 let arr = [1, [2, [3, 4]]];
 function flatten(arr) {
     return arr.reduce(function(prev, next){
         return prev.concat(Array.isArray(next) ? flatten(next) : next)
     }, [])
 }
 console.log(flatten(arr));//  [1, 2, 3, 4,5]

(3)扩展运算符实现

这个方法的实现,采用了扩展运算符和 some 的方法,两者共同使用,达到数组扁平化的目的:

 let arr = [1, [2, [3, 4]]];
 function flatten(arr) {
     while (arr.some(item => Array.isArray(item))) {
         arr = [].concat(...arr);
     }
     return arr;
 }
 console.log(flatten(arr)); //  [1, 2, 3, 4,5]

(4)split 和 toString

可以通过 split 和 toString 两个方法来共同实现数组扁平化,由于数组会默认带一个 toString 的方法,所以可以把数组直接转换成逗号分隔的字符串,然后再用 split 方法把字符串重新转换为数组,如下面的代码所示:

 let arr = [1, [2, [3, 4]]];
 function flatten(arr) {
     return arr.toString().split(',');
 }
 console.log(flatten(arr)); //  [1, 2, 3, 4,5]

通过这两个方法可以将多维数组直接转换成逗号连接的字符串,然后再重新分隔成数组。

(5)* ES6 中的 flat*

我们还可以直接调用 ES6 中的 flat 方法来实现数组扁平化。flat 方法的语法:arr.flat([depth])

其中 depth 是 flat 的参数,depth 是可以传递数组的展开深度(默认不填、数值是 1),即展开一层数组。如果层数不确定,参数可以传进 Infinity,代表不论多少层都要展开:

 let arr = [1, [2, [3, 4]]];
 function flatten(arr) {
   return arr.flat(Infinity);
 }
 console.log(flatten(arr)); //  [1, 2, 3, 4,5]

可以看出,一个嵌套了两层的数组,通过将 flat 方法的参数设置为 Infinity,达到了我们预期的效果。其实同样也可以设置成 2,也能实现这样的效果。在编程过程中,如果数组的嵌套层数不确定,最好直接使用 Infinity,可以达到扁平化。

(6)正则和 JSON 方法

在第4种方法中已经使用 toString 方法,其中仍然采用了将 JSON.stringify 的方法先转换为字符串,然后通过正则表达式过滤掉字符串中的数组的方括号,最后再利用 JSON.parse 把它转换成数组:

 let arr = [1, [2, [3, [4, 5]]], 6];
 function flatten(arr) {
   let str = JSON.stringify(arr);
   str = str.replace(/([|])/g, '');
   str = '[' + str + ']';
   return JSON.parse(str); 
 }
 console.log(flatten(arr)); //  [1, 2, 3, 4,5]