【javascript】keyとvalueが逆になったオブジェクトを作りたい【リスペクト記事】

### この記事のハイライト

```diff_javascript
- const reverseMap = Object.fromEntries(Object.entries(greetingMessageMap).map(a => a.reverse()))
+ const reverseMap = Object.fromEntries(Object.entries(greetingMessageMap).map(([key, value]) => [value, key]))
```

以上

---

:::note warn
批判・反論記事ではありません
:::

いつも我々を楽しませてくれる記事をたくさん投稿してくれているやめ太郎氏、先日 Twitter にてこのような投稿が。
内容は書いてある通りで、「key と value が逆になったオブジェクトを作る」ためのスニペットです。
シンプルにワンライナーで使えて、とても役に立つ TIPS ですが、自分だったらこう書くかなーという部分があったので記事にしてみました。

https://twitter.com/Yametaro1983/status/1590881059633520641?s=20&t=mEeSxyimPImm6Mw2_DNdbg

まず、件のスニペットがこちら。このコードがどのような処理を行っているのか、紐解いてみます。

```javascript
const reverseMap = Object.fromEntries(Object.entries(greetingMessageMap).map(a => a.reverse()))
```

こちらが元となるオブジェクトです。

```javascript
const greetingMessageMap = {
  morning: "おはよう",
  afternoon: "こんにちは",
  evening: "こんばんは"
}
```

### ① Object.entries

まず `Object.entries` メソッドを使って、オブジェクトを key と value の配列に変換します。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/entries

```javascript
const entries = Object.entries(greetingMessageMap)
console.log(entries)

> [
>   [ 'morning', 'おはよう' ],
>   [ 'afternoon', 'こんにちは' ],
>   [ 'evening', 'こんばんは' ]
> ]
```

`morning: "おはよう"` が `[ 'morning', 'おはよう' ]`、さらにそれを囲う `{}` が `[]` となり、オブジェクトから配列（配列の配列）に変換されていることがわかります。

### ② Array.prototype.map, Array.prototype.reverse

次に、`map` メソッドと `reverse` メソッドを使い、key と value を入れ替えます。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse

```javascript
const reverse = entries.map(a => a.reverse())
console.log(reverse)

> [
>   [ 'おはよう', 'morning' ],
>   [ 'こんにちは', 'afternoon' ],
>   [ 'こんばんは', 'evening' ]
> ]
```

もともとの配列では `[ 'morning', 'おはよう' ]`（`[ key, value ]`） となっていたものが `[ 'おはよう', 'morning' ]`（`[ value, key ]`）となっており、key と value が入れ替わっているということがわかります。

#### 自分だったら

今回「自分だったらこう書くかなー」と思った部分は、`reverse` メソッドを使った部分です。

```javascript
// もともと
entries.map(a => a.reverse())

// 自分だったら ver.
entries.map(([key, value]) => [value, key])
```

処理結果については全く変わりません。
`map` メソッドによってデータ（`[ 'morning', 'おはよう' ]` ）を 1 件ずつ取り出し、配列の 0 番目の要素である key と 1 番目の要素である value を入れ替えていることに変わりありません。

しかし、`a => a.reverse()` では「key と value を入れ替えている」という意図が伝わりづらいのではないか、と思い筆を取った次第です。

 `([key, value]) => [value, key]` とすることで「key と value を取り出し、入れ替えた上で改めて配列として返却する」としたほうが、処理の意図が伝わりやすいのではないかと思いました。

### ③ Object.fromEntries

最後に `Object.fromEntries` でオブジェクトに変換し、完成です。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries

```javascript
const reverseMap = Object.fromEntries(reverse)
console.log(reverseMap)

> {
>   "おはよう": "morning",
>   "こんにちは": "afternoon",
>   "こんばんは": "evening"
> }
```

以上です。ご清聴ありがとうございました。



#### 余談

記事を書いてて思いついた別解的なものも載せておきます。
Object.entries, reduce, Object.assign を使ってます。

```javascript
Object.entries(greetingMessageMap).reduce((val, [key, value]) => Object.assign(val, {[value]: key}), {})
```

こちらは Object.assign の代わりにスプレッド構文を使ってます。

```javascript
Object.entries(greetingMessageMap).reduce((val, [key, value]) => ({ ...val, [value]: key }), {})
```

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax