📘

javascriptで取得した売り上げデータの重複月を合計する

2021/06/24に公開

背景

売り上げデータをまとめたいが、SQLが得意でない私は上手く GROUP BYできず、サーバー側の権限で設定の変更もできない。
そんな時にやむを得ずjs側でうまい具合にやるようになった時に役立つスクリプトを組んだ(誰得)

例えば下記のようなデータが取得できたとする。

  {month: 07, sale: 1111},
  {month: 07, sale: 1111},
  {month: 08, sale: 2222},
  {month: 08, sale: 3333},
  {month: 08, sale: 1000},
  {month: 10, sale: null},
  {month: 10, sale: null},
  {month: 11, sale: 1111},
  {month: 12, sale: 1111},

上記データの重複している月の売り上げ(sale)を合計して重複を解消したい。

ソースコード

const list = [
  {month: 07, sale: 1111},
  {month: 07, sale: 1111},
  {month: 08, sale: 2222},
  {month: 08, sale: 3333},
  {month: 08, sale: 1000},
  {month: 10, sale: null},
  {month: 10, sale: null},
  {month: 11, sale: 1111},
  {month: 12, sale: 1111},
]
// ひとつ前の要素を比較対象にする
var prevIndex = 0

const listUpdate = list.filter(function(value, i, list) {
    if (i > 0) {
      prevIndex = i - 1
    }
  
    if (list[prevIndex].sale !== null && value.sale !== null) {
      resultSales = Number(list[prevIndex].sale + value.sale)
      list[i].sale = resultSales
    }

    return i === 0 ? true : list[prevIndex].month !== value.month
  })

console.log(listUpdate)

コード解説

const listUpdate = list.filter( function(value, i, list) {

jsのfilter関数を使用する配列に対して動作する関数で、中身はコールバック関数で、
引数は、第1引数:配列の値、第2引数:要素番号、第3引数:配列の名前(対象としては指定した配列になるが、名前を変えても良い 例:list->list2)
条件がtrueの要素を返す。
その条件は下記

return i === 0 ? true : list[prevIndex].month !== value.month

要素番号が0の場合はtrueを返すようにしている。
0のひとつ前の要素は0になるため、一致してしまうのでtrueを返す。
現在の要素番号の値は valueで取れる。しかしひとつ前の要素は listを使って要素番号を指定する必要がある。

if (i > 0) {
      prevIndex = i - 1
    }

初回でひとつ前の要素が-1になるのを防ぐ

    if (list[prevIndex].sale !== null && value.sale !== null) {
      resultSales = Number(list[prevIndex].sale + value.sale)
      list[i].sale = resultSales
    }

お互いにnullでなければ売上を合算して現在の要素番号の売り上げに代入する

以上で取得したうりげデータの重複付きを合計するスクリプトができた
codepen->https://codepen.io/t1k2a/pen/VwpoLdb

懸念

実は下記のような場合だと計算結果がおかしくなってしまう

const list = [
  {month: 09, sale: 0},
  {month: 09, sale: 1000},
]

// コード省略

// 結果: {"month": 9, "sale": 0}

nullを型指定で否定しているから(!==)0は含まれない認識だが、違うのか・・・?
この辺よくわからぬ\(^^)/

参考文献

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://qiita.com/diescake/items/70d9b0cbd4e3d5cc6fce
https://www.infoscoop.org/blogjp/2012/05/02/js-array-splice/
https://qiita.com/_masa_u/items/4633519d6642098cd8fe

Discussion