Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group same elements in JS array, but only when consecutive

I have an array of objects representing a series of 'messages' in a chat. I want to group messages that are consecutively created by the same 'user', which is stored in each array item. Here's a simplified version of what I'm trying to do:

[
    { message: "One", user: "Bob" },
    { message: "Two", user: "Bob" },
    { message: "Three", user: "Bob" },
    { message: "Hello", user: "Sam" },
    { message: "Hello", user: "Bob" },
    { message: "Hello", user: "Sam" },
    { message: "Hello", user: "Sam" }
]

should be turned into:

[
    [
        { message: "One", user: "Bob"},
        { message: "Two", user: "Bob" },
        { message: "Three", user: "Bob" }
    ],
    [
        { message: "Hello", user: "Sam" }
    ],
    [
        { message: "Hello", user: "Bob" }
    ],
    [
        { message: "Hello", user: "Sam" },
        { message: "Hello", user: "Sam" }
    ]
]

Is there any easy way to do this? I couldn't find an answer/algorithm anywhere.

like image 856
Pal Kerecsenyi Avatar asked Dec 08 '22 13:12

Pal Kerecsenyi


2 Answers

You can do that with the reduce method.

const data = [
  { message: "One", user: "Bob" },
  { message: "Two", user: "Bob" },
  { message: "Three", user: "Bob" },
  { message: "Hello", user: "Sam" },
  { message: "Hello", user: "Bob" },
  { message: "Hello", user: "Sam" },
  { message: "Hello", user: "Sam" }
];

const result = data.reduce((acc, value) => {
  // compare the current value with the last item in the collected array
  if (acc.length && acc[acc.length - 1][0].user == value.user) {
    // append the current value to it if it is matching
    acc[acc.length - 1].push(value);
  } else {
    // append the new value at the end of the collected array
    acc.push([value]);
  }

  return acc;
}, []);
  
console.log(result);
like image 181
KARASZI István Avatar answered Dec 10 '22 01:12

KARASZI István


You could do something like this:

const messages = [
    { message: "One", user: "Bob" },
    { message: "Two", user: "Bob" },
    { message: "Three", user: "Bob" },
    { message: "Hello", user: "Sam" },
    { message: "Hello", user: "Bob" },
    { message: "Hello", user: "Sam" },
    { message: "Hello", user: "Sam" }
]

let currentUser;
let groupedMessages = [];

for (message of messages) {

  if (message.user !== currentUser) {
    groupedMessages.push([]);
    currentUser = message.user;
  }
  groupedMessages[groupedMessages.length - 1].push(message)
}

console.log(groupedMessages);
like image 32
Jordan Soltman Avatar answered Dec 10 '22 02:12

Jordan Soltman