按多个属性对对象数组进行分组
我有一系列通知,我想按某些条件进行分组(例如 facebook 的通知)
var data = [
{ id: 1, type: 'shop.follower', by: { id: 2, name: 'User B', }, in: null, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:21:20' },
{ id: 2, type: 'product.liked', by: { id: 2, name: 'User B' }, in: { id: 1, ... }, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:24:45' },
{ id: 3, type: 'product.commented', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: '2021-02-20 20:01:39', created_at: '2021-02-19 16:21:43' },
{ id: 4, type: 'product.liked', by: { id: 4, name: 'User D' }, in: { id: 1, ... }, read_at: '2021-03-29 15:14:21', created_at: '2021-03-28 08:11:50' },
{ id: 5, type: 'product.liked', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: null, created_at: '2021-03-28 08:12:24' },
{ id: 6, type: 'shop.follower', by: { id: 5, name: 'User E' }, in: null, read_at: null, created_at: '2021-05-23 10:02:21' },
{ id: 7, type: 'shop.follower', by: { id: 3, name: 'User C' }, in: null, read_at: null, created_at: '2021-07-18 10:31:12' },
{ id: 8, type: 'comment.replied', by: { id: 4, name: 'User D' }, in: { id: 6, ... }, read_at: null, created_at: '2021-07-24 08:34:25' },
]
假设我想按日期按降序分组
所以我有这个代码:
function sortByDate(array, desc = true) {
if (desc === false) {
// Ascending order
return array.sort((a, b) => {
if (new Date(a.created_at) > new Date(b.created_at)) {
return 1
} else {
return -1
}
return 0
})
}
// Descending order
return array.sort((a, b) => {
if (new Date(a.created_at) < new Date(b.created_at)) {
return 1
} else {
return -1
}
return 0
})
}
所以现在我们有这样的数组:
[
{ id: 8, type: 'comment.replied', by: { id: 4, name: 'User D' }, in: { id: 6, ... }, read_at: null, created_at: '2021-07-24 08:34:25' },
{ id: 7, type: 'shop.follower', by: { id: 3, name: 'User C' }, in: null, read_at: null, created_at: '2021-07-18 10:31:12' },
{ id: 6, type: 'shop.follower', by: { id: 5, name: 'User E' }, in: null, read_at: null, created_at: '2021-05-23 10:02:21' },
{ id: 5, type: 'product.liked', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: null, created_at: '2021-03-28 08:12:24' },
{ id: 4, type: 'product.liked', by: { id: 4, name: 'User D' }, in: { id: 1, ... }, read_at: '2021-03-29 15:14:21', created_at: '2021-03-28 08:11:50' },
{ id: 3, type: 'product.commented', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: '2021-02-20 20:01:39', created_at: '2021-02-19 16:21:43' },
{ id: 2, type: 'product.liked', by: { id: 2, name: 'User B' }, in: { id: 1, ... }, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:24:45' },
{ id: 1, type: 'shop.follower', by: { id: 2, name: 'User B', }, in: null, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:21:20' },
]
现在我们的数组已经排序,我创建了一个函数:
// https://www.tutorialspoint.com/most-efficient-method-to-groupby-on-an-array-of-objects-in-javascript
function groupByProperty(array, property) {
return array.reduce((acc, object) => {
const key = object[property]
if (! acc[key]) {
acc[key] = []
}
acc[key].push(object)
return acc
}, {})
}
然后,我运行此代码
Object.values(groupByProperty(data, 'type'))
哪个返回:
[
[
{ id: 8, type: 'comment.replied', by: { id: 4, name: 'User D' }, in: { id: 6, ... }, read_at: null, created_at: '2021-07-24 08:34:25' }
],
[
{ id: 7, type: 'shop.follower', by: { id: 3, name: 'User C' }, in: null, read_at: null, created_at: '2021-07-18 10:31:12' },
{ id: 6, type: 'shop.follower', by: { id: 5, name: 'User E' }, in: null, read_at: null, created_at: '2021-05-23 10:02:21' },
{ id: 1, type: 'shop.follower', by: { id: 2, name: 'User B', }, in: null, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:21:20' }
],
[
{ id: 5, type: 'product.liked', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: null, created_at: '2021-03-28 08:12:24' },
{ id: 4, type: 'product.liked', by: { id: 4, name: 'User D' }, in: { id: 1, ... }, read_at: '2021-03-29 15:14:21', created_at: '2021-03-28 08:11:50' },
{ id: 2, type: 'product.liked', by: { id: 2, name: 'User B' }, in: { id: 1, ... }, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:24:45' }
],
[
{ id: 3, type: 'product.commented', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: '2021-02-20 20:01:39', created_at: '2021-02-19 16:21:43' }
],
]
我想按以下类别对这些通知进行分组:
- 相同
type(我已经在我的函数中介绍了这一点groupByProperty()) - 同样
in: { id: ... }除了type: shop.follower - 如果 #1 和 #2 为真,则检查
created_at: ...日期间隔在 10 分钟之间的类似对象 - 如果我们有#3(多个)这样的情况,如果其中一个有
read_at= null,那么它将是未读通知,获取最新(最新)日期
在
id: 4and 中id: 5,时间戳之间的间隔小于 10 分钟,因此我希望将其分组为一个
示例预期输出:
[
[
{ by: {id: 4, name: "User D"}, created_at: "2021-07-24 08:34:25", id: 8, in: {id: 6}, read_at: null, type: "comment.replied" }
],
[
{ by: {id: 3, name: "User C"}, created_at: "2021-07-18 10:31:12", id: 7, in: null, read_at: null, type: "shop.follower" }
],
[
{ by: {id: 5, name: "User E"}, created_at: "2021-05-23 10:02:21", id: 6, in: null, read_at: null, type: "shop.follower" }
],
[
{ by: {id: 3, name: "User C"}, created_at: "2021-03-28 08:12:24", id: 5, in: {id: 1}, read_at: null, type: "product.liked" },
{ by: {id: 4, name: "User D"}, created_at: "2021-03-28 08:11:50", id: 4, in: {id: 1}, read_at: "2021-03-29 15:14:21", type: "product.liked" }
],
[
{ by: {id: 3, name: "User C"}, created_at: "2021-02-19 16:21:43", id: 3, in: {id: 1}, read_at: "2021-02-20 20:01:39", type: "product.commented" }
],
[
{ by: {id: 2, name: "User B"}, created_at: "2020-08-02 05:24:45", id: 2, in: {id: 1}, read_at: "2021-01-03 10:15:43", type: "product.liked" }
],
[
{ by: {id: 2, name: "User B"}, created_at: "2020-08-02 05:21:20", id: 1, in: null, read_at: "2021-01-03 10:15:43", type: "shop.follower" }
],
]
浏览器中的示例:
|------------------------------------------------------------------------------|
| - (UNREAD) User D replied to your comment ....., 2021-07-24 08:34:25 |
| - (UNREAD) User C start follow your shops ....., 2021-07-18 10:31:12 |
| - (UNREAD) User E start follow your shops ....., 2021-05-23 10:02:21 |
| - (UNREAD) User C and D liked your product ....., 2021-03-28 08:12:24 | <= (Please pay attention)
| - (READ) User C commented on your product ....., 2021-02-19 16:21:43 |
| - (READ) User B liked your product ....., 2020-08-02 05:24:45 |
| - (READ) User B start follow your shops ....., 2020-08-02 05:21:20 |
这是我尝试的代码 find interval between 10 minutes
function inRangeBetween(val, min, max) {
if (val >= min && val <= max) {
return true
}
return false
}
var startingPoint = { min: 0, max: 0, type: null },
newData = []
for (var i = 0; i < data.length; i++) {
if (startingPoint.min < 1
&& startingPoint.max < 1
&& startingPoint.type === null) {
console.log('Starting point')
var start = new Date(data[i].created_at)
startingPoint.min = start.getTime()
startingPoint.max = start.getTime() + (10 * 60000)
startingPoint.type = data[i].type
newData[data[i].type] = []
} else {
// startingPoint has values
if (inRangeBetween(new Date(data[i].created_at).getTime(), startingPoint.min, startingPoint.max
&& data[i].type === startingPoint.type) {
console.log(`Pushing new object to key ${data[i].type}`)
newData[data[i].type].push(data[i])
} else {
// Set new values for startingPoint, and start again comparing
console.log('Starting point values changes')
startingPoint.min = new Date(data[i]).getTime()
startingPoint.min = new Date(data[i]).getTime() + (10 * 60000)
startingPoint.type = data[i].type
newData[data[i].type] = []
newData[data[i].type].push(data[i])
}
}
}
// Not working
如何实现这一目标?(卡在这个问题5天了)
提前致谢