學習軌道
/
JavaScript
JavaScript
/
練習
/
Elyse 的轉化魔法
Elyse 的轉化魔法

Elyse 的轉化魔法

學習練習

簡介

在 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

準備好開始 Elyse 的轉化魔法 了嗎?

註冊 Exercism,透過 37 個概念159 個練習 和真人引導來學習並精通 JavaScript,全部免費。