chst365's blog chst365's blog
首页
  • Git
  • 网络
  • 操作系统
  • 浏览器
  • webpack
  • JavaScript
  • TypeScript
  • 性能
  • 工程化
  • React
  • 编程题
  • React技术揭秘
  • 算法
  • Node
  • 编码解码
  • NodeJS系列
  • Linux系列
  • JavaScript系列
  • HTTP系列
  • GIT系列
  • ES6系列
  • 设计模式系列
  • CSS系列
  • 小程序系列
  • 数据结构与算法系列
  • React系列
  • Vue3系列
  • Vue系列
  • TypeScript系列
  • Webpack系列
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

chst365

DIV工程师
首页
  • Git
  • 网络
  • 操作系统
  • 浏览器
  • webpack
  • JavaScript
  • TypeScript
  • 性能
  • 工程化
  • React
  • 编程题
  • React技术揭秘
  • 算法
  • Node
  • 编码解码
  • NodeJS系列
  • Linux系列
  • JavaScript系列
  • HTTP系列
  • GIT系列
  • ES6系列
  • 设计模式系列
  • CSS系列
  • 小程序系列
  • 数据结构与算法系列
  • React系列
  • Vue3系列
  • Vue系列
  • TypeScript系列
  • Webpack系列
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 浏览器

  • webpack

  • TypeScript

  • 性能

  • 工程化

  • React

  • JavaScript

  • 编程题

    • 实现一个trim方法
    • 实现一个deepClone方法
    • 实现add(1)(2)(3)
    • 大数相加
    • 拍平数组flat
      • Array.prototype.flat()
        • 实现一个数组拍平flat函数
        • 用 reduce 实现 flat 函数
        • 用栈的思想实现 flat 函数
        • 通过传入整数参数控制拉平层数
        • 使用 Generator 实现 flat 函数
        • 实现在原型链上重写flat函数
        • 考虑数组空位情况
    • 实现防抖、节流函数
    • 反转字符串
    • 数组去重
    • 实现千位分隔符
    • 回文数
    • 实现一个模板引擎
    • 判断一个数是否是素数
    • 获取n以内所有的素数
  • React技术揭秘

  • 算法

  • 前端
  • 编程题
chst365
2022-09-02
目录

拍平数组flat

# Array.prototype.flat()

const animals = ["🐷", ["🐶", "🐂"], ["🐎", ["🐑", ["🐲"]], "🐛"]];

// 不传参,默认拉平一层
animals.flat();
// [ '🐷', '🐶', '🐂', '🐎', [ '🐑', [ '🐲' ] ], '🐛' ]

// 传一个整数参数,整数即拉平的层数
animals.flat(2);
// [ '🐷', '🐶', '🐂', '🐎', '🐑', [ '🐲' ], '🐛' ]

// Infinity 作为参数,无论嵌套多少层,都转为一维数组
animals.flat(Infinity);
// ['🐷', '🐶', '🐂', '🐎', '🐑', '🐲', '🐛']

// 传入 <= 0的整数 返回原数组
animals.flat(0);
animals.flat(-10);
// ["🐷", ["🐶", "🐂"], ["🐎", ["🐑", ["🐲"]], "🐛"]]

// 如果原数组有空位,flat()方法会跳过空位。
["🐷", "🐶", "🐂", "🐎", ,].flat();
// ["🐷", "🐶", "🐂", "🐎"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# Array.prototype.flat() 特性

  • 用于将嵌套数组拉平,变成一维数组。该方法返回一个新数组,对原数组没影响
  • 不传参,默认拉平一层;传入一个整数,表示拉平的层数
  • 传入 <= 0 的整数,返回原数组
  • Infinity 关键字作为参数,无论嵌套多少层,都转为一维数组
  • 若原数组有空位,会跳过空位

# 实现一个数组拍平flat函数

# 实现思路

  • 遍历数组的每一个元素
  • 判断元素是否是数组
  • 将数组的元素展开一层
const arr = [1, 2, 3, 4, [1, 2, 3, [1, 2, 3, [1, 2, 3]]], 5, "string", { name: "弹铁蛋同学" }];
// concat + 递归
function flat(arr) {
  let arrResult = [];
  arr.forEach(item => {
    if (Array.isArray(item)) {
      arrResult = arrResult.concat(arguments.callee(item));   // 递归
      // 或者用扩展运算符
      // arrResult.push(...arguments.callee(item));
    } else {
      arrResult.push(item);
    }
  });
  return arrResult;
}
flat(arr)
// [1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, "string", { name: "弹铁蛋同学" }];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 用 reduce 实现 flat 函数

const arr = [1, 2, 3, 4, [1, 2, 3, [1, 2, 3, [1, 2, 3]]], 5, "string", { name: "弹铁蛋同学" }]

const flat = arr => {
    return arr.reduce((pre, cur) => {
        return pre.concat(Array.isArray(cur) ? flat(cur) : cur);
    }, []);
};
1
2
3
4
5
6
7

# 用栈的思想实现 flat 函数

function flat(arr) {
    const result = [];
    const stack = [].concat(arr); // 将数组元素拷贝至栈,直接赋值会改变原数组
    while (stack.length !== 0) {
        const val = stack.pop();
        Array.isArray(val) ? stack.push(...val) : result.unshift(val);
    }
    return result;
}
1
2
3
4
5
6
7
8
9

# 通过传入整数参数控制拉平层数

function flat(arr, num = 1) {
    return num > 0 ? arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? flat(cur, num - 1) : cur), []) : arr.slice();
}
1
2
3

# 使用 Generator 实现 flat 函数

function* flat(arr, num = 1) {
    for (const item of arr) {
        if (Array.isArray(item) && num > 0) {
            yield* flat(item, num - 1);
        } else {
            yield item;
        }
    }
}
// 调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象
// 即遍历器对象,需用一次扩展符运算得到结果
console.log([...flat(arr)]);
1
2
3
4
5
6
7
8
9
10
11
12

# 实现在原型链上重写flat函数

Array.prototype.fakeFlat = function (num = 1) {
    if (!Number(num) || Number(num) < 0) return this;
    let arr = this.concat();
    while (num > 0) {
        if (arr.some(x => Array.isArray(x))) {
            arr = [].concat.apply([], arr);
            console.log(arr);
        } else {
            break;
        }
        num--;
    }
    return arr;
};
console.log(arr.fakeFlat(Infinity));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 考虑数组空位情况

ES5大多数数组方法对空位的处理都会选择跳过空位:forEach()、filter()、reduce()、every()、some()

const arr = [1, [3, 4], , ,];
// reduce + 递归
Array.prototype.fakeFlat = function(num = 1) {
  if (!Number(num) || Number(num) < 0) {
    return this;
  }
  let arr = [].concat(this);
  return num > 0
    ? arr.reduce(
        (pre, cur) =>
          pre.concat(Array.isArray(cur) ? cur.fakeFlat(--num) : cur),
        []
      )
    : arr.slice();
};
arr.fakeFlat()
// [1, 3, 4]

// foEach + 递归
Array.prototype.fakeFlat = function(num = 1) {
  if (!Number(num) || Number(num) < 0) {
    return this;
  }
  let arr = [];
  this.forEach(item => {
    if (Array.isArray(item)) {
      arr = arr.concat(item.fakeFlat(--num));
    } else {
      arr.push(item);
    }
  });
  return arr;
};
arr.fakeFlat()
// [1, 3, 4]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# ES5 与 ES6 对数组空位的处理

ES5在多数情况下回忽略空位

  • forEach()、filter()、reduce()、every()和some() 都会跳过空位
  • map()会跳过空位,但会保留这个值
  • join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串

ES6明确将空位转为undefined

  • entries()、keys()、values()、find()和findIndex()会将空位处理成undefined
  • for...of循环会遍历空位
  • fill()会将空位视为正常的数组位置
  • copyWithin()会连空位一起拷贝
  • 扩展运算符也会将空位转为undefined
  • Array.from方法会将数组的空位转为undefined
#前端#编程题
上次更新: 2022/09/02, 17:10:06
大数相加
实现防抖、节流函数

← 大数相加 实现防抖、节流函数→

最近更新
01
面试官
03-27
02
this&指针&作用域&闭包
03-27
03
前端
03-27
更多文章>
Theme by Vdoing | Copyright © 2019-2025 chst365 | 豫ICP备17031889号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式