从lodash源码看数组扁平化实现

lodash源码

import isFlattenable from './isFlattenable.js'

/**
 * The base implementation of `flatten` with support for restricting flattening.
 *
 * @private
 * @param {Array} array The array to flatten.
 * @param {number} depth The maximum recursion depth.
 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
 * @param {Array} [result=[]] The initial result value.
 * @returns {Array} Returns the new flattened array.
 */
function baseFlatten(array, depth, predicate, isStrict, result) {
  predicate || (predicate = isFlattenable)
  result || (result = [])

  if (array == null) {
    return result
  }

  for (const value of array) {
    if (depth > 0 && predicate(value)) {
      if (depth > 1) {
        // Recursively flatten arrays (susceptible to call stack limits).
        baseFlatten(value, depth - 1, predicate, isStrict, result)
      } else {
        result.push(...value)
      }
    } else if (!isStrict) {
      result[result.length] = value
    }
  }
  return result
}

export default baseFlatten

lodash是通过递归加数组打散来完成数组扁平化的。这种方法优点是能控制数组最多扁平化几层。

./isFlattenable.js用来检测是否是数组或类数组:

import isArguments from '../isArguments.js'

/** Built-in value reference. */
const spreadableSymbol = Symbol.isConcatSpreadable

/**
 * Checks if `value` is a flattenable `arguments` object or array.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
 */
function isFlattenable(value) {
  return Array.isArray(value) || isArguments(value) ||
    !!(value && value[spreadableSymbol])
}

export default isFlattenable

通过代码,我们可以看到,它是通过递归完成的。其中有三个参数需要解析一下:

参数值解析
depth表示最多可扁平化多少层
predicate填入false表示用默认的函数判断是否可以对每一项数据进行扁平化,也可自己写个函数判断
isStrict表示是否在扁平化之后的数组中留下不能扁平化的数据

我们可以这样调用

在这里插入图片描述

其它扁平化方式

正则实现也是先将数组转换成字符串的表达形式,这里将数组转成字符串我们使用JSON.stringify方法,将数组转换成一个由括号包裹、元素间以逗号相隔的字符串,例如"[1, [2, [3, [4, 5]]], 6]",从转换后的字符可以发现,每一对括号包着的范围就是一个层级,数组的展平就是将内部的层级全部消除,只保留最外层,在这里,就是将括号全部替换成空字符,得到一个元素以逗号相隔字符串,最后将利用JSON.parse方法解析成数组对象。

let arr = [1, [2, [3, [4, 5]]], 6];
function flatten(arr) {
  let str = JSON.stringify(arr);
  str = str.replace(/(\[|\])/g, '');
  // 拼接最外层,变成JSON能解析的格式
  str = '[' + str + ']';
  return JSON.parse(str); 
}
console.log(flatten(arr)); //  [1, 2, 3, 4,5]

这种方式在处理引用数据类型上有局限性,同时还要注意元素是否是JSON的合法数据类型。

参考博客:
https://juejin.cn/post/6998879961935249422#comment

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值