数组

数组变换 属于 JavaScript

20 个练习

关于 数组变换

在 JavaScript 中,Array类有许多强大的内置方法可以用来转换数组。有了这些方法,把一个数组转换成另一个数组会容易得多,比用简单的 for 循环或其他更直接的操作省事不少。

有些方法是纯函数,也就是说它们不会修改原数组,而是返回一个新数组。另一些方法则会改变调用它们的那个数组,并且不会返回修改后的数组。

下面介绍一些最常用的数组转换方法。完整的方法列表可以在 MDN 文档 中找到。

map(纯函数)

根据作为实参传入的函数对每个元素进行转换,从而创建一个新数组。这些回调函数通常写成箭头函数。

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

const newArr = arr.map((value) => value - 1);
console.log(newArr);
// => [0, 1, 2, 3]
console.log(arr);
// => [1, 2, 3, 4]

值得注意的是,结果数组的长度始终与原数组相同。

filter(纯函数)

给定一个过滤函数(对应当保留的元素返回 true,对应当移除的元素返回 false),过滤当前数组并创建一个新数组。

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

arr.filter((value) => value % 2 === 0);
// => [2, 4]

reduce(纯函数)

用一个函数把数组归约为单个值,该函数接收一个_累加器_和数组的当前元素作为形参。这个函数说明了如何把当前元素合并进累加器,并返回将在下一次迭代中使用的累加器。

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

// Get the sum of elements
arr.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
// => 10

// Classify the numbers by whether they are odd or not
arr.reduce(
  (accumulator, currentValue) => {
    if (currentValue % 2 === 0) {
      accumulator.even.push(currentValue);
    } else {
      accumulator.odd.push(currentValue);
    }

    return accumulator;
  },
  { even: [], odd: [] },
);
// => { even: [2, 4], odd: [1, 3] }

reverse

反转数组中的元素。

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

arr.reverse();
// => [4, 3, 2, 1]

这个方法会修改调用它的数组。

slice(纯函数)

给定起始下标和结束下标,从调用它的数组中创建一个子数组。

结束下标处的元素不会被包含在内。 此外,所有参数都是可选的: 起始下标默认为 0,结束下标默认为数组长度。

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

arr.slice(1, 2); // [2]
arr.slice(1); // [2, 3, 4]
// You can also use negative numbers, that represent the indexes
// starting from the end of the array
arr.slice(-2); // [3, 4]

splice

删除或替换数组中的元素,并/或添加新元素。 它接收以下参数:

  • 开始修改数组的元素下标
  • 要删除的元素个数
  • 要插入数组的元素(可选)

splice 返回被删除的元素。

const arr = ['1', '2', '5', '6'];

// Insert an element at index 2
arr.splice(2, 0, '3');
console.log(arr);
// => ['1', '2', '3', '5', '6']

// Remove 2 elements, starting at index 3 and insert 2 elements
const removed = arr.splice(3, 2, '4', '5');
console.log(removed);
// => ['5', '6']
console.log(arr);
// => ['1', '2', '3', '4', '5']

// Remove 1 element at index 1
arr.splice(1, 1);
console.log(arr);
// => ['1', '3', '4', '5']

sort

默认情况下,sort 会先把数组元素转换成字符串,然后进行字符串比较,以此对元素排序(参见比较概念)。 排序是_原地_进行的,也就是说原数组会被修改。 sort 还会返回这个修改后的数组,如果你想在它后面链式调用其他方法,这很方便。

const arr = ['c', 'a', 'z', 'b'];
const result = arr.sort();
console.log(result);
// => ['a', 'b', 'c', 'z']
console.log(arr);
// => ['a', 'b', 'c', 'z']
Caution

这种默认行为在你尝试对数字排序时会导致错误的结果。

const arr = [3, 1, 2, 10];
arr.sort();
// => [1, 10, 2, 3]
// Because the string '10' comes before '2' in dictionary order.

要自定义排序行为,可以把一个比较函数作为实参传入。 比较函数本身会以数组中的两个元素作为实参来调用。 它需要返回以下内容:

  • 如果第一个实参应排在第二个之前,返回一个负数
  • 如果第一个实参应排在第二个之后,返回一个正数
  • 如果两个元素的顺序应保持不变,返回 0

这样一来,只要传入正确的比较函数,数字排序的问题就能解决。

下面是一个用自定义比较函数对对象数组排序的例子。

const arr = [3, 1, 2, 10];
arr.sort((a, b) => a - b);
// => [1, 2, 3, 10]
// "a - b" is negative when b is greater than a, positive when
// a is greater than b and 0 when they are equal.

下面是一个用自定义比较函数对对象数组排序的例子。

const arr = [
  { name: 'Lydia', age: 7 },
  { name: 'Anne', age: 34 },
  { name: 'Holger', age: 59 },
];

arr.sort((item1, item2) => {
  if (item1.name < item2.name) {
    return -1;
  }
  if (item1.name > item2.name) {
    return 1;
  }
  return 0;
});
// => [ { name: 'Anne', age: 34 }, { name: 'Holger', age: 59 },
// { name: 'Lydia', age: 7 } ]

自 2019 年起,语言规范规定排序必须是稳定的,但对性能(时间与空间复杂度)不作任何保证。

通过 GitHub 编辑 该链接会在新窗口或标签页中打开

学习 数组变换