4

突然変異なしで関数ごとにグループを効率的に実装する方法はありますか?

単純な実装:

var messages = [
  {insertedAt: "2021-01-10"},
  {insertedAt: "2021-01-12"},
  {insertedAt: "2021-01-13"},
  {insertedAt: "2021-01-13"},
  {insertedAt: "2021-01-13"},
  {insertedAt: "2021-01-14"},
  {insertedAt: "2021-01-15"},
  {insertedAt: "2021-01-15"},
  {insertedAt: "2021-01-16"},
  {insertedAt: "2021-01-17"},
  {insertedAt: "2021-01-17"},
  {insertedAt: "2021-01-17"},
  {insertedAt: "2021-01-18"},
  {insertedAt: "2021-01-18"},
]

var messagesGroupedByDate = messages.reduce(function (data, message) {
  if (
    data.some(function (point) {
      return point.date === message.insertedAt;
    })
  ) {
    return data.map(function (point) {
      if (point.date === message.insertedAt) {
        return {
          date: point.date,
          count: (point.count + 1) | 0,
        };
      } else {
        return point;
      }
    });
  } else {
    return data.concat([
      {
        date: message.insertedAt,
        count: 1,
      },
    ]);
  }
}, []);


console.log(messagesGroupedByDate);

議論のために、これをより一般的にする必要はありません。私が直面している問題は、3 回ループしていることです。

  • Array.prototype.reduceループオーバーする必要がある1回messages
  • Array.prototype.some結果の配列に日付キーが既に存在するかどうかを確認するために一度
  • 日付キーが既に存在する場合は、再度ループしてArray.prototype.map配列の特定の要素を更新します
  • それ以外の場合は、新しい要素を含む新しい配列が返されます

ReScript でこれを効率的にする良い方法が本当にない場合は、この関数に生の JavaScript をいつでも使用できますが、これを突然変異なしで効率的に行うことができるかどうかに興味があります。

4

4 に答える 4

1
于 2021-01-18T23:25:17.110 に答える
1

データを a に追加し、Map()配列に変換してからオブジェクトに変換するだけです。リクエストどおりに何も変更しません。

これをさらに単純化するかもしれませんが、今は午前 5 時で、私の脳は眠っています。

var messages = [
  {insertedAt: "2021-01-10"},
  {insertedAt: "2021-01-12"},
  {insertedAt: "2021-01-13"},
  {insertedAt: "2021-01-13"},
  {insertedAt: "2021-01-13"},
  {insertedAt: "2021-01-14"},
  {insertedAt: "2021-01-15"},
  {insertedAt: "2021-01-15"},
  {insertedAt: "2021-01-16"},
  {insertedAt: "2021-01-17"},
  {insertedAt: "2021-01-17"},
  {insertedAt: "2021-01-17"},
  {insertedAt: "2021-01-18"},
  {insertedAt: "2021-01-18"},
];

const mapped = new Map();

messages.forEach(message => {
    // if date already seen before, increment the count
    if (mapped.has(message.insertedAt)) {
        const count = mapped.get(message.insertedAt);
        mapped.set(message.insertedAt, count+1);
    } else {
        // date never seen before, add to map with initial count
        mapped.set(message.insertedAt, 1);
    }
});

const msgArr = Array.from(mapped);

const final = msgArr.map(([date, count])=> ({date, count}));

console.log(final);

于 2021-01-18T23:19:03.167 に答える