🦖

うわっ…私のコード、遅すぎ…? filter編

2023/12/20に公開1

ある日のコードくんとパフォ姉さん

コードくん: 「JavaScriptでさ、データがいっぱいある時の話なんやけど...」

パフォ姉さん: 「あぁ、またあんたの"データ山盛り問題"か?」

コードくん: 「せやせや、商品ごとに注文を探すんやけど、こんなんでええんかなぁ〜」

const orders = [{ productId: 1, ... }, { productId: 2, ... }, ...]; // 注文いっぱい
const products = [{ id: 1, ... }, { id: 2, ... }, ...]; // 商品のリスト

let filteredOrders = [];
for (const product of products) {
  const productOrders = orders.filter(order => order.productId === product.id);
  filteredOrders.push(...productOrders);
}

パフォ姉さん: 「何やってんねん!それ、めっちゃ時間かかるやん!」

コードくん: 「ええやん、時間はタップリあるし...」

パフォ姉さん: 「時間あっても無駄にするな!。"filter" を使うとな、毎回その商品IDの注文を探すために全注文を最初から最後まで見なあかん。商品の数だけその作業が繰り返されるから、データが多いとすごい時間がかかるんや。」

コードくん: 「ほな、どうしたらええん?」

パフォ姉さん: 「ここは "Map" を使おう!」

Mapとは

コードくん: 「"Map"? なんやそれ、"Sports Music Assemble People"のことか?」

パフォ姉さん: 「それはSMAPや!ってかボケがマイナーすぎるわ!」

パフォ姉さん: 「"Map"ってのは、キーと値のペアを効率よく管理するためのJavaScriptのオブジェクトや。キーには何でも(この場合は商品ID)、値には関連するデータ(注文情報)を入れるんや。」

パフォ姉さん: 「これで注文を商品IDごとに仕分けてみ。一回のループで全部済ますんやで。」

const ordersMap = new Map();
for (const order of orders) {
  if (!ordersMap.has(order.productId)) {
    ordersMap.set(order.productId, []);
  }
  ordersMap.get(order.productId).push(order);
}

let filteredOrders = [];
for (const product of products) {
  filteredOrders.push(...(ordersMap.get(product.id) || []));
}

コードくん: 「へぇ、すごいな!これでサクサク動くやんけ!」

パフォ姉さん: 「そうやろ!これでサクサク動くで!」

コードくん: 「すごいやん!"Map"、便利やなぁ〜」

パフォ姉さん: 「せやろ?これで時間の節約や!」

Mapの注意点

パフォ姉さん: 「でも注意やで。"Map"は生成時にちょっとしたオーバーヘッドがあるから、使う場面をよう選ばんとあかんで。一度作った後は素早いけど、毎回作るのはあかんで。」

コードくん: 「なるほどなぁ。用途に応じて使い分けるんやな。」

パフォ姉さん: 「そうや。賢く使って、速くてスマートなコードを書こうな!」

まとめ

コードくん: 「"filter" ループ問題は "Map" でサクッと解決や!」

Discussion

standard softwarestandard software

こんな感じでも書けるかなと。

const ordersMap = new Map();
for (const order of orders) {
  const orders = ordersMap.get(order.productId);
  if (!orders) {
    ordersMap.set(order.productId, [order])
  } else {
    orders.push(order);
  }
}
const filteredOrders = [...orderMap.values()].flat(1);