I have an array of notifications that I want to group by certain conditions (like facebook's notifications)
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: 4, 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' },
]
Let's say I want to group by date in descending order
So I have this code:
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
})
}
So now we have array like this:
[
{ 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: 4, 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' },
]
Now that our array is sorted, I created a function:
// 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
}, {})
}
Then, I run this code
Object.values(groupByProperty(data, 'type'))
Which return:
[
[
{ 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: 4, 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' }
],
]
I don't know how to group object that has date gap interval between 10 minutes
Expected output:
- Same
type
- Same
in: { id: ... }
(Except fortype: shop.follower
) - If #1 and #2 true, check for similar objects with
created_at: ...
date gap between 10 minutes - If we have a case like #3 (multiple), if one among it has
read_at
= null, then itunread notification
, then get the latest (newest) date
In id: 4
and id: 5
, the gap between timestamps is less than 10 minutes, so I want it to group as one (Again, sorry for bad english)
example:
|------------------------------------------------------------------------------|
| - (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 |
This is the code I tried to find gap 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
How to achieve this? (Stuck for this problem for 5 days)
Thanks in advance
from Grouping array of objects by multiple properties
No comments:
Post a Comment