专业编程基础技术教程

网站首页 > 基础教程 正文

帮你精通JS: array.flat与flatMap用法指南

ccvgpt 2024-08-12 14:52:37 基础教程 15 ℃

众所周知,JavaScript是当今流行语言中对函数式编程支持最好的编程语言。前文中,我们分解介绍了帮助我们组织思维的array.reduce方法和array.map方法。这两种方法的共同点都是对array作转换和变形。

本文我们继续探讨第三种对array变形的函数 array.flat.

帮你精通JS: array.flat与flatMap用法指南

1.1 array.flat() 概述

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

const arr1 = [0, 1, 2, [3, 4]];

console.log(arr1.flat());
// expected output: [0, 1, 2, 3, 4]

const arr2 = [0, 1, 2, [[[3, 4]]]];

console.log(arr2.flat(2));
// expected output: [0, 1, 2, [3, 4]]

1.2 array.flat() 语法

var newArray = arr.flat([depth])

参数

depth 可选 指定要提取嵌套数组的结构深度,默认值为 1。

返回值

一个包含将数组与子数组中所有元素的新数组。

案例01 扁平化嵌套数组

var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

案例02 扁平化数组与空项

var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]

案例03 用reduce构建flat

var arr = [1, 2, [3, 4]];

// 展开一层数组
arr.flat();
// 等效于
arr.reduce((acc, val) => acc.concat(val), []);
// [1, 2, 3, 4]

// 使用扩展运算符 ...
const flattened = arr => [].concat(...arr);


2.1 array.flatMap

flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 连着深度值为1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。

var new_array = arr.flatMap(function callback(currentValue[, index[, array]]) {
    // return element for new_array
}[, thisArg])

参数

callback 可以生成一个新数组中的元素的函数,可以传入三个参数:
- currentValue 当前正在数组中处理的元素
- index可选 可选的。数组中正在处理的当前元素的索引。
- array可选 可选的。被调用的 map 数组

thisArg可选 可选的。执行 callback 函数时 使用的this 值。

返回值

一个新的数组,其中每个元素都是回调函数的结果,并且结构深度 depth 值为1。

描述

flatMap 方法与 map 方法和深度depth为1的 flat 几乎相同.

案例 01 map() 与 flatMap()

var arr1 = [1, 2, 3, 4];

arr1.map(x => [x * 2]);
// [[2], [4], [6], [8]]

arr1.flatMap(x => [x * 2]);
// [2, 4, 6, 8]

// only one level is flattened
arr1.flatMap(x => [[x * 2]]);
// [[2], [4], [6], [8]]

虽然上面的代码使用 map 和 flatMap 好像都可以,但这只能展示如何使用 flatMap。

所以,为了更好的展示 flatMap 的作用,下面我们将包含几句话的数组拆分成单个词组成的新数组。

let arr1 = ["it's Sunny in", "", "California"];

arr1.map(x => x.split(" "));
// [["it's","Sunny","in"],[""],["California"]]

arr1.flatMap(x => x.split(" "));
// ["it's","Sunny","in", "", "California"]

注意,输出列表长度可以不同于输入列表长度。

案例 02 在一个 map() 期间增加或去除一些项

flatMap 能用于在map期间增删项目(也就是修改items的数量)。换句话说,它允许你遍历很多项使之成为另一些项(靠分别把它们放进去来处理),而不是总是一对一。 从这个意义上讲,它的作用类似于 filter的对立面。只需返回一个1项元素数组以保留该项,返回一个多元素数组以添加项,或返回一个0项元素数组以删除该项。

// Let's say we want to remove all the negative numbers and split the odd numbers into an even number and a 1
let a = [5, 4, -3, 20, 17, -33, -4, 18]
//       |\  \  x   |  | \   x   x   |
//      [4,1, 4,   20, 16, 1,       18]

a.flatMap( (n) =>
  (n < 0) ?      [] :
  (n % 2 == 0) ? [n] :
                 [n-1, 1]
)

// expected output: [4, 1, 4, 20, 16, 1, 18]

案例03 替代方案

var arr = [1, 2, 3, 4];

arr.flatMap(x => [x, x * 2]);
// is equivalent to
arr.reduce((acc, x) => acc.concat([x, x * 2]), []);
// [1, 2, 2, 4, 3, 6, 4, 8]

请注意,这是低效的,并且应该避免大型阵列:在每次迭代中,它创建一个必须被垃圾收集的新临时数组,并且它将元素从当前的累加器数组复制到一个新的数组中,而不是将新的元素添加到现有的数组中。

Tags:

最近发表
标签列表