LoginSignup
1
1

More than 1 year has passed since last update.

Object.values() が便利だから(?) Javascript では配列よりハッシュを積極的に使おう

Last updated at Posted at 2021-06-10

まぁ表題のままなので、あまり書くような事もないんですが。

つまり

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.values(object1));
// expected output: Array ["somestring", 42, false]

こういう事なんですが、具体的にどういう場面で使えるのか、というところについて書きたいと思います。


6/12追記 : コメントで「この例ならMAPの方がいい」という指摘をいただきました。
MAPはキーに Object も使えるし forEachvalues も実装されているので、MAPの方がよさそうです。
なのでまぁ、 Object.values() はそれはそれで便利だよという感じで見ていただければと思います。


配列管理

const user = {
  id: 123456,
  name: 'Alice',
  mail: 'alice@example.com'
}

こういうデータがあったとして

  • id はいわゆる主キーとして機能する
  • id は規則的ではない
  • id 以外の情報は書き換えが存在する

このデータを沢山管理する必要があった時に素朴に思いつくのは配列だと思います。

const users = [
  {
    id: 123456,
    name: 'Alice',
    mail: 'alice@example.com'
  },
  {
    id: 573940,
    name: 'Bob',
    mail: 'bobie@example.com'
  },
  ....
]

こうすると「 id: 999 のデータを探したい」ってなった時にこうなると思います

const userThreeNine = users.find(u => u.id === 999)

情報を更新したいってなったらこうなりますね。実際はもっと多くのプロパティ持ってるでしょうし、ロジック分けるのもめんどうなので「情報を全部貰ってリプレイスする」方がいいと思うので、こうなる事の方が多いと思います。

Object.assign(users.find(u => u.id === 999), newData)

一番面倒なのはこの配列からデータを削除したい場合です。多分こうなると思います。

users.splice(users.findIndex(u => u.id === 999), 1)

配列使ってるんだからこうだよね、という感じのごくごくあたりまえのコードに見えますが、パッと見でこのコードを理解できますか?

あとは、たとえば大量のデータを処理しようとした時にかかるオーダーは全体数を $n$、更新数を $m$ とした場合に $ O(n,m) = log(n)*m $ です。 別に目を顰めるオーダーではないですが、減らせるんなら減らしたいですよね。

ハッシュ管理

なので、こうしてしまいましょう。

const userThreeNine = {
  id: 999,
  name: 'Three Nine',
  mail: 'three.nine@example.com'
} 
users[hogeUser.id] = hogeUser

検索も存在確認も削除も以下の通りです。

const id = 999
const userThreeNine = users[id] // 検索

const hogeUserNewData = {...}
users[hogeUserNewData.id] = hogeUserNewData // 更新

const deleteUserId = 666
delete users[deleteUserId] // 削除

コードも直感的になったし、勿論検索コストは $ O(n, m) = m $ です。
これで万事解決!といいたいところですが……

配列だからこそできたこと

  • 各要素でのソート
  • 主キー以外での検索/フィルタリング

とかとか、「配列でできた事ができなくなったじゃないか!」と思っているでしょう。
素朴に書くなら、例えば検索なら for...in を使えばできそうです。

const hasHogeIsHuga (user) {
  return user.hoge === 'huga'
}
const findSomtehing (users, hasHogeIsHuga) {
  const result = []
  for(const p in users){
    if( hasHogeIsHuga(users[p]) ){
      result.push(users[p])
    }
  }
  return result
}

:thinking: :thinking: :thinking: :thinking: :thinking:
なんじゃこれ。ってなりますね。

そこで Object.values()

一番最初に書いたように、この関数はオブジェクトを配列の形に開いてくれます。
なので例えば

// フィルタリング
const hasHogeHugaUsers = Object.values(users).filter(hasHogeIsHuga)

// ソート
const usersSortedByPoint = Object.values(users).sort((a,b) => a.point - b.point)

のように書けるわけです。便利!

という訳で

  • ハッシュ管理は見やすいよ
  • Object.values() は便利だよ

という話でした。
見やすいコードに貢献してくれると思います。

1
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1