javascript - 如何在没有突变的情况下按功能创建有效的组?
问题描述
有没有一种方法可以有效地实现按功能分组而不发生突变?
天真的实现:
- 重新编写游乐场
- JavaScript(见下文)
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);
为了争论,没有必要使它更通用。我面临的问题是我循环了三次:
- 一次
Array.prototype.reduce
需要循环messages
- 一次
Array.prototype.some
查看日期键是否已存在于结果数组中 - 在日期键已经存在的情况下,我们再次循环
Array.prototype.map
以更新数组的特定元素 - 否则,返回一个包含新元素的新数组
如果在 ReScript 中没有真正提高效率的好方法,那么我总是可以为这个函数使用原始 JavaScript,但我很好奇是否有可能在没有突变的情况下有效地做到这一点。
解决方案
您可以通过按日期构建计数对象来更简单地进行分组,然后根据需要使用Object.entries
andArray.map
将其转换为对象数组:
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 = Object.entries(
messages.reduce((data, message) => {
data[message.insertedAt] = data[message.insertedAt] || 0;
data[message.insertedAt]++;
return data;
}, {})
).map(([date, count]) => ({ date, count }));
console.log(messagesGroupedByDate);
您还可以直接从中的值创建一个对象messages
,然后通过循环更新计数messages
:
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 data = Object.fromEntries(messages.map(({ insertedAt: date }) => [ date, 0 ]));
messages.forEach(({ insertedAt: date }) => data[date]++);
const messagesGroupedByDate = Object.entries(data).map(([date, count])=> ({date, count}));
console.log(messagesGroupedByDate);
推荐阅读
- swift - 如何从另一个文件更新 NSStausItem?
- google-app-engine - 如何在 Google Cloud AppEngine 上强制使用 https
- python-3.x - 如何修复 plotly trace1 = go.Scatter() 未在 python 上按需要绘制
- android - 在 TableLayout Android 中绘制圆圈
- docker - 创建 Docker 自己的 node_modules
- laravel - 非常简单的 Laravel + Vue 应用程序上的“未捕获 RangeError:超出最大调用堆栈大小”
- kubernetes - 拒绝从同一集群上的 CronJob 连接到 Kubernetes Pod
- html - 样式化浏览器颜色的字符
- svelte - 无法启动 Svelte
- google-cloud-platform - 健康检查在 https 中失败,但在 http 中没有