arch nemesis
arch nemesis

Reputation: 31

How to group an array of objects according to a property in that object

I have an array of objects like these

[
{
        id: 536,
        user_id: 87,
        event_type: 'CA',
        purpose: 1,
        timestamp: 1435678384
      },
      {
        id: 5368,
        user_id: 87,
        event_type: 'CA',
        purpose: 4,
        timestamp: 1435678384
      },
      {
        id: 53688,
        user_id: 87,
        event_type: 'CA',
        purpose: 9,
        timestamp: 1435678385
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 7,
        timestamp: 1435678386
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 5,
        timestamp: 1435678396
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 8,
        timestamp: 1435678397
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 2,
        timestamp: 1435678398
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 3,
        timestamp: 1435678350
      }
]

I want to group all the objects inside the array by their timestamp, so if the timestamps in the objects are located within 5ms of each other, combine the objects into one single array

So in this case I want the output to look like

[
    [{
            id: 536,
            user_id: 87,
            event_type: 'CA',
            purpose: 1,
            timestamp: 1435678384
        },
        {
            id: 5368,
            user_id: 87,
            event_type: 'CA',
            purpose: 4,
            timestamp: 1435678384
        },
        {
            id: 53688,
            user_id: 87,
            event_type: 'CA',
            purpose: 9,
            timestamp: 1435678385
        },
        {
            id: 588,
            user_id: 87,
            event_type: 'CA',
            purpose: 7,
            timestamp: 1435678386
        }
    ],
    [{
            id: 588,
            user_id: 87,
            event_type: 'CA',
            purpose: 5,
            timestamp: 1435678396
        },
        {
            id: 588,
            user_id: 87,
            event_type: 'CA',
            purpose: 8,
            timestamp: 1435678397
        },
        {
            id: 588,
            user_id: 87,
            event_type: 'CA',
            purpose: 2,
            timestamp: 1435678398
        }
    ], {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 3,
        timestamp: 1435678350
    }
]

I have tried to use an array method filter on this to get the desired code. However I can only segregate one group, I cannot have a 2D array like this. Notice the last object which cannot be grouped(timestamp is far beyond 5ms of any other object's timestamp) is not in an array.

My efforts so far are not much, Here is what I have tried

ca.forEach((cur, index) => {
            let newArr = []
            let grouped = ca.filter((target, innerIndex) => {
                    if ((cur.timestamp - target.timestamp) < 5) {
                    return true
                } else {
                    return false
                }
            })

Any help to solve this will be greatly appreciated!

Upvotes: 0

Views: 154

Answers (2)

captain hak
captain hak

Reputation: 912

What you can try is the reduce function: see here my code in stackblitz

var firstArray = [
{
        id: 536,
        user_id: 87,
        event_type: 'CA',
        purpose: 1,
        timestamp: 1435678384
      },
      {
        id: 5368,
        user_id: 87,
        event_type: 'CA',
        purpose: 4,
        timestamp: 1435678384
      },
      {
        id: 53688,
        user_id: 87,
        event_type: 'CA',
        purpose: 9,
        timestamp: 1435678385
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 7,
        timestamp: 1435678386
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 5,
        timestamp: 1435678396
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 8,
        timestamp: 1435678397
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 2,
        timestamp: 1435678398
      },
      {
        id: 588,
        user_id: 87,
        event_type: 'CA',
        purpose: 3,
        timestamp: 1435678350
      }
];

var secondArray = firstArray.sort((a, b)=>{
    return a.timestamp-b.timestamp
}).reduce(
  (accumulator,current)=>{
    if(
      typeof accumulator[accumulator.length-1]==='object' &&
      current.timestamp - accumulator[accumulator.length-1][0].timestamp <5
    ) {
      accumulator[accumulator.length-1].push(current);
    } else {
      accumulator.push([current]);
    }
    return accumulator;
  },
  []
);


console.log(secondArray);

EDIT: I didn't see the 5 ms need but you can adapt the if to suit your need, tell me if you want me to do it. ;)

EDIT2: I added the sort function in order to sort by timestamp like that we're sure the minus operation is in the good order and I did the minus operation in the if of the reduce. Let me know if that helps

Upvotes: 2

user9308412
user9308412

Reputation:

You can create one big array. And small reusable array that you put all the objects that are related and then push the tempArray to the allArray Array and clear it and then do the same for all the other objects. Get all the object with that certain property using the foreach method of the array.

Let allArray = [ ];

Let tempArray = [ ];

allArray.push(tempArray);

Upvotes: 0

Related Questions