轨道
/
JavaScript
JavaScript
/
练习
/
埃莉丝的变换魔法
埃莉丝的变换魔法

埃莉丝的变换魔法

学习练习

简介

在 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']

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

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

下面是一个示例,展示如何使用自定义比较函数来排序对象数组。

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 } ]

说明

Elyse 是一位见习魔术师,她还在继续自己的训练。别人会给她一副牌,她要试着把这副牌变个样:让某些牌出现、消失、改变数字,或者彻底重新排列。 为了简单起见,她通常只用编号 1 到 10 的牌开始,不过有些魔术可能会变出数字更大的牌。

1. 把每张牌都翻倍

Elyse 想把牌堆里每张牌的数字翻倍。这样变出来的牌可能比 1 到 10 更大。

const deck = [1, 2, 3, 4, 10];
seeingDouble(deck);
// => [2, 4, 6, 8, 20]

2. 把牌堆里出现的每个 3 都变成三张

Elyse 想把牌堆里出现的每个 3 都变成三张。如果一副牌里原本只有一张 3,变完魔术后,原来的那张 3 就会变成三张 3。

const deck = [1, 3, 9, 3, 7];
threeOfEachThree(deck);
// => [1, 3, 3, 3, 9, 3, 3, 3, 7]

3. 找出牌堆正中间的两张牌

Elyse 会拿一副 10 张的牌,让除了中间两张以外的所有牌都消失。

const deck = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
middleTwo(deck);
// => [5, 6]

4. 最外面两张牌会重新出现在牌堆中间

Elyse 想把牌堆最上面和最下面的两张牌移到中间,并且颠倒它们的顺序。

你可以假设牌堆里的牌数是偶数。

const deck = [1, 2, 3, 5, 6, 10];
sandwichTrick(deck);
// => [2, 3, 10, 1, 5, 6]

5. 所有不是 2 的牌都会消失

Elyse 今天最喜欢的数字是 2。在这个魔术里,牌堆中所有不是 2 的牌都会消失。

const deck = [1, 2, 3, 4, 10, 2];
twoIsSpecial(deck);
// => [2, 2]

6. 把洗乱的牌堆变成完全有序的牌堆

Elyse 想展示自己完美重排这些牌的本领,不管它们被洗得多乱。

const deck = [10, 1, 5, 3, 2, 8, 7];
perfectlyOrdered(deck);
// => [1, 2, 3, 5, 7, 8, 10]

7. 重新排列牌堆

Elyse 想改变牌堆里牌的顺序。 变完魔术后,现在最上面的那张牌应该跑到牌堆最下面。第二张牌应该跑到倒数第二张的位置,以此类推。

const deck = [10, 1, 5, 3, 2];
reorder(deck);
// => [2, 3, 5, 1, 10]
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
JavaScript Exercism

准备好开始 埃莉丝的变换魔法 了吗?

注册 Exercism,借助 37 个概念159 个练习 和真人导师指导,学习并掌握 JavaScript,全部免费。