Malakiof
Malakiof

Reputation: 108

Json and group by solution

I'm trying to select the last messages of an inbox and group them in a list by the topic_id. i want to display the last message of each topic.

the array looks like this:

[{
"id":"5",
"topic_id":"4",
"message_from":"24",
"message":"how do you do?",
"date":"2015-01-13 15:34:59"
},
{
"id":"6",
"topic_id":"1",
"message_from":"33",
"message":"go go go!!",
"date":"2015-01-13 13:35:06"
},
{
"id":"7",
"topic_id":"4",
"message_from":"33",
"message":"Je suis charlie",
"date":"2015-01-14 16:24:46"
},....

is there a solution to do it without a loop?

Upvotes: 0

Views: 39

Answers (1)

Andy
Andy

Reputation: 63540

You can't do this without loops, but you can make this easier by breaking down the sequence of events into smaller functions. You might not like this approach, but it's the cleanest imo. Alternatively you can use a third-party library (underscore, perhaps?) that allows you to run groupings on data.

Basically, get a list of all the topic_ids for all records, loop over that topic_id array and pull out the last record for each and add that to an output array.

// Get a list of all the topic ids - no duplicates
function getTopicIds(arr) {
  var out = [];
  arr.forEach(function (el) {
    if (out.indexOf(el.topic_id) === -1) out.push(el.topic_id);
  });
  return out;
}

// Given a topic_id, filter the array for only those records
// sort in desc order by id, and return the first record.
// Given that each record has a unique id, and we know that older
// messages will have higher ids, it's easier to sort by id than
// date here 
function getLastMsg(id, arr) {
  return arr.filter(function (el) {
    return el.topic_id === id;
  }).sort(function (a, b) { return +b.id - +a.id; })[0];
}

// return a array of the last messages for each topic_id
// in the records array
function getLastMsgs(arr) {
  return getTopicIds(arr).map(function (id) {
    return getLastMsg(id, arr);
  });
}

var result = getLastMsgs(arr);

DEMO

Upvotes: 1

Related Questions