JavaScriptの配列操作に役立つ13のヒントとトリック


以下はDuomly ( [Webサイト](https://duomly.com) / [Twitter](https://twitter.com/duomly) )による記事、[13 useful JavaScript array tips and tricks you should know](https://dev.to/duomly/13-useful-javascript-array-tips-and-tricks-you-should-know-2jfo)の日本語訳です。

[Duomly](https://www.duomly.com/)はプログラミング学習コースを提供しているWebサイトです。
ただランディングページにたいしたことが書いてないので、詳細はよくわかりません。
ここはもう少し書いておいてほしいところ。

# 13 useful JavaScript array tips and tricks you should know

配列はJavaScriptで最も一般的な概念のひとつであり、内部に格納されたデータを操作する手段は多数存在します。
配列はJavaScriptの最も基本的なトピックであり、プログラミング学習パスの最初に学習するものだという前提のうえで、この記事ではあなたが知らないかもしれない、しかしコーディングにおいてはとても役立つかもしれない、幾つかのトリックを紹介します。
さっそく始めましょう。


## 1. Remove duplicates from an array

配列から重複した値を削除する方法は、JavaScriptの質問の中でも非常によく見かけるものです。
ここでは、新しめの機能である`Set()`を使った高速で簡単な解決策を紹介します。
これには2種類、`.from()`を使う方法、およびスプレッド構文`...`を使う方法があります。

```js
	var fruits = ["banana", "apple", "orange", "watermelon", "apple", "orange", "grape", "apple"];

	// fromを使う方法
	var uniqueFruits = Array.from(new Set(fruits));
	console.log(uniqueFruits); // ["banana", "apple", "orange", "watermelon", "grape"]
	// ...を使う方法
	var uniqueFruits2 = [...new Set(fruits)];
	console.log(uniqueFruits2); // ["banana", "apple", "orange", "watermelon", "grape"]
```

簡単ですね。


## 2. Replace the specific value in an array

コーディング中に、配列の一部の値だけを書き換えなければならない事態に陥ることはよくあります。
これを実現するとても短い記法があるのですが、もしかしたらご存じないかもしれません。
このために`.splice`を使うことができます。
これは3つの引数を取り、ひとつめが変更する開始位置のインデックス、ふたつめが変更する数、そして3つめ以降は存在すればかわりに新しい値を入れ込みます。

```js
	var fruits = ["banana", "apple", "orange", "watermelon", "apple", "orange", "grape", "apple"];
	fruits.splice(0, 2, "potato", "tomato");
	console.log(fruits); // ["potato", "tomato", "orange", "watermelon", "apple", "orange", "grape", "apple"]
```


## 3. Map array without .map()

全員が`.map()`を使いこなしているだろうと思いますが、`.map()`を使わずに同じ効果を得られる全く別のソリューションが存在します。
それは`.from()`メソッドです。

```js
	var friends = [
	    { name: 'John', age: 22 },
	    { name: 'Peter', age: 23 },
	    { name: 'Mark', age: 24 },
	    { name: 'Maria', age: 22 },
	    { name: 'Monica', age: 21 },
	    { name: 'Martha', age: 19 },
	]

	var friendsNames = Array.from(friends, ({name}) => name);
	console.log(friendsNames); // ["John", "Peter", "Mark", "Maria", "Monica", "Martha"]
```


## 4. Empty an array

要素が大量に入った配列があるのですが、何らかの理由で全ての要素を削除したいとします。
要素をひとつひとつ削除したくないですか？
それを行うことは、わずか1行でできます。
`length`を0にすると中身が全部消えます。

```js
	var fruits = ["banana", "apple", "orange", "watermelon", "apple", "orange", "grape", "apple"];

	fruits.length = 0;
	console.log(fruits); // []
```


## 5. Convert array to an object

今手元にひとつの配列がありますが、諸事情により同じデータを持つオブジェクトが必要になりました。
配列をオブジェクトに変換する最も手っ取り早い方法は、スプレッド構文を使用することです。

```js
	var fruits = ["banana", "apple", "orange", "watermelon"];
	var fruitsObj = { ...fruits };
	console.log(fruitsObj); // {0: "banana", 1: "apple", 2: "orange", 3: "watermelon"}
```


## 6. Fulfill array with data

いちから配列を作成して何らかのデータで埋めたい場合、あるいは同じ値の並んだ配列が必要な場合、`.fill()`メソッドがその機能を持っています。

```js
	var newArray = new Array(10).fill("1");
	console.log(newArray); // ["1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"]
```


## 7. Merge arrays

`.concat()`を使わずに複数の配列をひとつにマージする方法を知っていますか？
その手段がここにはあります。
薄々お察しかとは思いますが、スプレッド構文`...`は配列操作したいときに非常に便利であり、今回も同じです。

```js
	var fruits = ["apple", "banana", "orange"];
	var meat = ["poultry", "beef", "fish"];
	var vegetables = ["potato", "tomato", "cucumber"];
	var food = [...fruits, ...meat, ...vegetables];
	console.log(food); // ["apple", "banana", "orange", "poultry", "beef", "fish", "potato", "tomato", "cucumber"]
```


## 8. Find the intersection of two arrays

ふたつの配列から共通項を抽出する処理は、JavaScriptの面接において直面する可能性の高い課題のひとつです。
あなたが配列のメソッドを理解しているか、ロジックを構築できるかの能力を見ることができるからです。
ここまでに紹介したメソッドのひとつを使うことで、ふたつの配列の共通部分を見つけることができます。
またチェックしている配列の値が重複していないことを確認するためには`.filter`と`.includes`メソッドを使用します。

```js
	var numOne = [0, 2, 4, 6, 8, 8];
	var numTwo = [1, 2, 3, 4, 5, 6];
	var duplicatedValues = [...new Set(numOne)].filter(item => numTwo.includes(item));
	console.log(duplicatedValues); // [2, 4, 6]
```


## 9. Remove falsy values from an array

まず"falseっぽい値"をはっきりさせましょう。
JavaScriptにおいて"falseっぽい値"とは、false、0、''、null、NaN、undefinedです。
これでfalseっぽい値を配列から削除する方法がわかりました。
それは`.filter()`メソッドです。

```js
	var mixedArr = [0, "blue", "", NaN, 9, true, undefined, "white", false];
	var trueArr = mixedArr.filter(Boolean);
	console.log(trueArr); // returns ["blue", 9, true, "white"]
```

## 10. Get random value form the array

配列からランダムに値を選択しなければならない状況に追い込まれることが人生にはよくあります。
簡単高速で短くクリーンなコードを保つには、配列長からランダムなインデックス番号を生成するとよいでしょう。

```js
	var colors = ["blue", "white", "green", "navy", "pink", "purple", "orange", "yellow", "black", "brown"];
	var randomColor = colors[(Math.floor(Math.random() * (colors.length)))]
```

## 11. Reversing an array

配列を逆さにしたい場合、複雑なループと関数を使って新たな配列を作る必要はありません。
最初から専用のメソッドが用意されているので、1行で終わらせることができます。

```js
	var colors = ["blue", "white", "green", "navy", "pink", "purple", "orange", "yellow", "black", "brown"];
	var reversedColors = colors.reverse();
	console.log(reversedColors); // ["brown", "black", "yellow", "orange", "purple", "pink", "navy", "green", "white", "blue"]
```

## 12. .lastIndexOf() method

JavaScriptには、指定された要素が最後に出現する位置のインデックスを返すという興味深いメソッドが存在します。
たとえば配列内に重複した値が存在する場合、それが最後に出現する位置を見つけることができます。

```js
	var nums = [1, 5, 2, 6, 3, 5, 2, 3, 6, 5, 2, 7];
	var lastIndex = nums.lastIndexOf(5);
	console.log(lastIndex); // 9
```

## 13. Sum all the values in the array

面接で頻繁に聞かれる、もうひとつの質問です。
特に難しいことはなく、`.reduce`メソッドひとつで解決することができます。

```js
	var nums = [1, 5, 2, 6];
	var sum = nums.reduce((x, y) => x + y);
	console.log(sum); // 14
```

## Conclusion

この記事では、ちょっとしたコーディングに役立ち、コードを短く簡潔に保つための13のヒントとトリックを紹介しました。
配列だけではなくそれ以外のデータ型にも、調べてみる価値のある様々な裏技があることを忘れないでください。
この記事で紹介したソリューションをあなたが気に入って、開発プロセスの改善に役立つことを願っています。

Have a nice coding!


# コメント欄

「Awesom!!」「Thanks!」
「`length=0`知らんかった、すごい！」

「Array.fromの第二引数知らなかった、勉強になる。」「`Array.map()`のかわりに常に`Array.from()`を用いなければならない、というのはよくわからない。」

「“”は"に修正すべき。」「そのとおり、記事にコードを含めるときは有効なコードであることを確認しよう。」

「3番目は配列っぽいオブジェクト、NodeListとかに使うとより便利だよね。」

「8番目、`Array.prototype.includes`は線形で`Set.prototype.has`は定数だから、大きい配列比較には`var duplicatedValues = […new Set(numOne)].filter(item => numTwo.includes(item));`のかわりに`let firstValues = [...new Set(numOne)];let duplicatedValues = numTwo.filter(item => firstValues.has(item));`ってしたほうがいい」「firstValuesは`has`持ってないから動かないよ。」「ほんとだ間違えた、正しくは`let firstValues = new Set(numOne);`だった。」

「11番目、`reverse()`はcolors自身も変更してしまう。変更したくないときは`[...colors].reverse();`ってしよう。」「`colors.slice().reverse()`でもいいぞ。」


# 感想

元記事は`“”`や`…`が全角で入っていたので、全て半角に修正しています。
英語圏の人が手動で`…`とか入れたり、さらに全角ダブルクォートの開きと閉じを使い分けるとは考えにくいですし、そもそも構文エラーなので、何らかの自動変換ライブラリが誤爆しているのだと思われます。
なかなか不思議なライブラリもあったものですね。

あと`var`ももう流行らないので`let`とかにしておいてほしいですね。

とはいえ細かい(パースエラーは細かくないが)点を除けば、配列を実用的に操作したいときに役立つトピックだと思います。
自分自身をさくさく書き換えているので何か言いたい人も出てきそうですが、そんなものより目の前で動くコードが必要なんですよ。



# 補足

`Array.splice`は、3番目以降の引数があれば削除位置に挿入される。
削除した数以上を指定しても全て挿入され、その後のインデックスが全部ずれる。
3番目以降の引数がなければ単に削除される。

```js
	var fruits = ["banana", "apple", "orange", "watermelon", "apple", "orange", "grape", "apple"];

	fruits.splice(0, 2, "a", "b", "c", "d");
	console.log(fruits); // ["a", "b", "c", "d", "orange", "watermelon", "apple", "orange", "grape", "apple"]

	fruits.splice(0, 9);
	console.log(fruits); // ["apple"]
```

配列要素を全削除するには、変な参照とかでもないかぎり、単純に上書きするほうが適切だろう。
結果が同じとはいえ、`length=0`は直感的操作とはあまり思えない。

```js
	var fruits = ["banana", "apple", "orange", "watermelon", "apple", "orange", "grape", "apple"];
	fruits = [];
	console.log(fruits); // []
```

falseっぽい値`false`、`0`、`''`、`null`、`NaN`、`undefined`のうち、NaNだけ`==false`がfalseになる。
NaNは自分自身も含めたあらゆる値との比較が`false`になるので仕様なのだがちょっとわかりにくい。