按具有条件和自定义键的对象数组分组
我有以下对象数组,
[{
a: 1,
created_on: '2021-04-23 10:00:01',
}, {
b: 1,
created_on: '2021-04-24 09:03:01',
}, {
b: 1,
created_on: '2021-04-24 13:03:01',
}]
首先,我需要使用忽略时间的日期分组。
所以,
{
"2021-04-23": [{
a: 1,
created_on: '2021-04-23 10:00:01',
}],
....
}
如果是类似的日期created_on: '2021-04-23',我可以使用lodash/groupBy.
我仍然可以使用它,但现在它涉及一些应用条件来将它们转换created_on为日期格式。
此外,我还需要按每个按日期结果分组的那些分组,以便它们created_on落在一个时间间隔内。
"SALES_SLOTS": [
{
"slot": "00:00-04:00"
},
{
"slot": "04:00-08:00"
},
{
"slot":"08:00-12:00"
},
{
"slot":"12:00-16:00"
},
{
"slot":"16:00-20:00"
},
{
"slot":"20:00-24:00"
}
],
所以,如果created_on: '2021-04-23 10:00:01',它应该进入组,
{
"08:00-12:00": [{
a: 1,
created_on: '2021-04-23 10:00:01',
}]
}
因此,第一个结果应按创建日期分组,然后每个组中的元素应按定义的时间段进一步分组。
我想,如果我可以按条件使用 group,我可以达到预期的结果。
回答
香草JS
使用Array#reduce带Map。
-
按日期分组相当简单,您可以
created_on.slice(0, 10)使用Map. -
然后我创建了一个辅助函数
getSlot,它根据经过的时间返回一个插槽。现在,由于您的插槽相当宽,因此仅测试小时部分就足够了。 -
接下来,对于每一组日期,再次使用
getSlothelper 将其按时间分组,Map并且使用Object.fromEntries您可以获得所需的对象。
注意:我在我的代码中使用了表达式而不是语句(使用逗号,默认参数),这只是一个优先选择。
const
arr = [{ a: 1, created_on: "2021-04-23 10:00:01" }, { b: 1, created_on: "2021-04-24 09:03:01" }, { b: 1, created_on: "2021-04-24 13:03:01" }],
slots = [{ slot: "00:00-04:00" }, { slot: "04:00-08:00" }, { slot: "08:00-12:00" }, { slot: "12:00-16:00" }, { slot: "16:00-20:00" }, { slot: "20:00-24:00" }],
grpDate = Array.from(
arr.reduce(
(m, o, _i, _arr, d = o.created_on.slice(0, 10)) => (
m.has(d) ? m.get(d).push(o) : m.set(d, [o]), m
),
new Map()
)
),
getSlot = (time) =>
slots
.find(({ slot }) => time >= slot.slice(0, 2) && time < slot.slice(6, 8))
.slot,
grpSlot = grpDate.map(([k, v]) =>
[k, Object.fromEntries(v.reduce(
(m, o, _i, _arr, slot = getSlot(o.created_on.slice(11, 13))) => (
m.has(slot) ? m.get(slot).push(o) : m.set(slot, [o]), m
),
new Map()
))]
);
console.log(Object.fromEntries(grpSlot));