トラック
/
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(純粋)

_アキュムレーター_と配列の現在の要素を仮引数にとる関数を使って、配列を1つの値にまとめます。この関数は、現在の要素をどのようにアキュムレーターへ統合するかを指示し、次の繰り返しで使われるアキュムレーターを返します。

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

並べ替えの動作をカスタマイズするには、比較関数を引数として渡します。 この比較関数は、配列の2つの要素を引数として呼び出されます。 そして、次のいずれかを返す必要があります。

  • 1つ目の引数を2つ目より前に並べ替える場合は負の数
  • 1つ目の引数を2つ目より後に並べ替える場合は正の数
  • 要素の順番をそのままにする場合は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は、修行を続けています。Elyseはカードの山札を渡され、その山札を変化させる技に挑みます。特定のカードを出現させたり、消したり、値を変えたり、まったく並べ替えたりするのです。 話を簡単にするため、たいていは1から10までの数字のカードから始めますが、なかにはより大きな数字のカードができてしまう技もあります。

1. すべてのカードを2倍にする

Elyseは、山札にあるすべてのカードの数値を2倍にしたいと考えています。1〜10より大きなカードができてしまうこともあります。

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

2. 山札にある3をそれぞれ3枚に増やす

Elyseは、山札にある3をすべて3枚ずつに増やしたいと考えています。もし山札に3が1枚だけあったら、技のあとでその1枚が3枚に置きかわります。

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

3. 山札のちょうど真ん中から2枚のカードを取り出す

Elyseは10枚の山札を受け取り、真ん中の2枚以外のカードをすべて消します。

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

4. 両端の2枚のカードが山札の真ん中に現れる

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は、山札のカードの順番を変えたいと考えています。 技のあと、現在一番上にあるカードは山札の一番下に来ます。2番目のカードは後ろから2番目に来ます。以下同様です。

const deck = [10, 1, 5, 3, 2];
reorder(deck);
// => [2, 3, 5, 1, 10]
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
JavaScript Exercism

Elyseの変換魔法を始める準備はできましたか?

Exercismに登録すれば、37個のコンセプト159個の演習、そして本物の人間によるメンタリングとともに、JavaScriptを学んでマスターできます。すべて無料です。