按多个属性对对象数组进行分组

我有一系列通知,我想按某些条件进行分组(例如 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' }
    ],
]

我想按以下类别对这些通知进行分组:

  1. 相同type(我已经在我的函数中介绍了这一点groupByProperty()
  2. 同样in: { id: ... }除了type: shop.follower
  3. 如果 #1 和 #2 为真,则检查created_at: ...日期间隔在 10 分钟之间的类似对象
  4. 如果我们有#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天了)

提前致谢

以上是按多个属性对对象数组进行分组的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>