0

What I want to achieve is to group objects together inside an array if the first two digits of the IDs matches. So given the below array of objects, I want to convert this ORIGINAL ARRAY:

[
    {
        "id": "0100",
        "name": "name 1",
        "message": "Lorem blah blah 1"
    },
    {
        "id": "0101",
        "name": "",
        "message": "Lorem blah blah 1.1"
    },
    {
        "id": "0200",
        "name": "name 2",
        "message": "Lorem blah blah 2"
    },
    {
        "id": "0201",
        "name": "",
        "message": "Lorem blah blah 2.1"
    },
    {
        "id": "0202",
        "name": "",
        "message": "Lorem blah blah 2.2"
    },
    {
        "id": "0300",
        "name": "name 3",
        "message": "Lorem blah blah 3"
    },
    {
        "id": "0301",
        "name": "",
        "message": "Lorem blah blah 3.1"
    },
    {
        "id": "0302",
        "name": "",
        "message": "Lorem blah blah 3.2"
    },
    {
        "id": "0303",
        "name": "",
        "message": "Lorem blah blah 3.3"
    },
    {
        "id": "0304",
        "name": "",
        "message": "Lorem blah blah 3.4"
    }
]

into this NEW ARRAY:

[
    {
        "id": "0100",
        "name": "name 1",
        "message": [
            "Lorem blah blah 1",
            "Lorem blah blah 1.1"
        ]
    },
    {
        "id": "0200",
        "name": "name 2",
        "message": [
            "Lorem blah blah 2",
            "Lorem blah blah 2.1",
            "Lorem blah blah 2.2"
        ]
    },
    {
        "id": "0300",
        "name": "name 3",
        "message": [
            "Lorem blah blah 3",
            "Lorem blah blah 3.1",
            "Lorem blah blah 3.2",
            "Lorem blah blah 3.3",
            "Lorem blah blah 3.4"
        ]
    }
]

The key thing to note is that if the first two digits of the IDs are identical, then add the messages in those objects together as seen in the NEW ARRAY.

As you can all see, @Nenad Vracar has demonstrated a decent answer to the above challenge, however, I have a further question involving yet another array:

`var data2 = [{"CandidateName": "Mary", "relatedId": ["0100"]},{ "CandidateName": "John", "relatedId": ["0200"]},{ "CandidateName":"Peter", "relatedId": ["0300"]},{ "CandidateName": "Paul", "relatedId": ["0300"]}];`

in which I want to pull the 'candidateName' and add it as an array to the original array, "result".

I've tried a data2.forEach loop inside the data1.reduce loop but it seems to hang.

var result = data.reduce(function(r, el) {

  // THIS INNER LOOP MAKES THE BROWSER HANG!!!
  data2.forEach(function (a){
    console.log('a',a); 
  });

  var e = el.id.slice(0, 2);
  if (!o[e]) {
    o[e] = {
      id: el.id,
      name: el.name,
      message: []
    }
    r.push(o[e]);
  }
  o[e].message.push(el.message);
  return r;
}, [])

I wonder if there's a more elegant, sophisticated method that will not break?

Mr. Benedict
  • 809
  • 2
  • 10
  • 15
  • It seems to be a sorted array – passion Sep 22 '16 at 09:20
  • How do I extend this question without losing momentum if I were I to ask it as a fresh question? May I ask my question in comments in here? if so, here goes? – Mr. Benedict Sep 25 '16 at 11:21
  • I come seeking further help. I have yet another array: `var data2 = [{"CandidateName": "Mary", "relatedId": ["0100"]},{ "CandidateName": "John", "relatedId": ["0200"]},{ "CandidateName":"Peter", "relatedId": ["0300"]},{ "CandidateName": "Paul", "relatedId": ["0300"]}];` in which I want to pull the 'candidateName' and add it as an array to the original array, "result". I've tried a data2.forEach loop inside the data1.reduce loop but it seems to hang. I wonder if there's a more elegant, sophisticated method that will not break? – Mr. Benedict Sep 25 '16 at 11:21

2 Answers2

6

You can use reduce() to return array and one object for grouping.

var data = [{"id":"0100","name":"name 1","message":"Lorem blah blah 1"},{"id":"0101","name":"","message":"Lorem blah blah 1.1"},{"id":"0200","name":"name 2","message":"Lorem blah blah 2"},{"id":"0201","name":"","message":"Lorem blah blah 2.1"},{"id":"0202","name":"","message":"Lorem blah blah 2.2"},{"id":"0300","name":"name 3","message":"Lorem blah blah 3"},{"id":"0301","name":"","message":"Lorem blah blah 3.1"},{"id":"0302","name":"","message":"Lorem blah blah 3.2"},{"id":"0303","name":"","message":"Lorem blah blah 3.3"},{"id":"0304","name":"","message":"Lorem blah blah 3.4"}];

var o = {}
var result = data.reduce(function(r, el) {
  var e = el.id.slice(0, 2);
  if (!o[e]) {
    o[e] = {
      id: el.id,
      name: el.name,
      message: []
    }
    r.push(o[e]);
  }
  o[e].message.push(el.message);
  return r;
}, [])

console.log(result)
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
  • Ahhh Nenad Vracar you're too fast for me. I was just setting up a fiddle of what I have tried for @Blaze Sahlzen and here you are with an actual working solution. Thank you pal. That's awesome!! Perfect answer. Not sure I can upvote yet but in case I cannot, I am symbolically voting you up buddy. This worked perfectly. – Mr. Benedict Sep 22 '16 at 09:41
  • Glad i could help. – Nenad Vracar Sep 22 '16 at 09:43
  • I come seeking further help. I have yet another array: `var data2 = [{"CandidateName": "Mary", "relatedId": ["0100"]},{ "CandidateName": "John", "relatedId": ["0200"]},{ "CandidateName":"Peter", "relatedId": ["0300"]},{ "CandidateName": "Paul", "relatedId": ["0300"]}];` in which I want to pull the 'candidateName' and add it as an array to the original array, "result". I've tried a data2.forEach loop inside the data1.reduce loop but it seems to hang. I wonder if there's a more elegant, sophisticated method that will not break? – Mr. Benedict Sep 25 '16 at 11:19
1

You could check for double zeroes and add the new group to the result set.

var data = [{ "id": "0100", "name": "name 1", "message": "Lorem blah blah 1" }, { "id": "0101", "name": "", "message": "Lorem blah blah 1.1" }, { "id": "0200", "name": "name 2", "message": "Lorem blah blah 2" }, { "id": "0201", "name": "", "message": "Lorem blah blah 2.1" }, { "id": "0202", "name": "", "message": "Lorem blah blah 2.2" }, { "id": "0300", "name": "name 3", "message": "Lorem blah blah 3" }, { "id": "0301", "name": "", "message": "Lorem blah blah 3.1" }, { "id": "0302", "name": "", "message": "Lorem blah blah 3.2" }, { "id": "0303", "name": "", "message": "Lorem blah blah 3.3" }, { "id": "0304", "name": "", "message": "Lorem blah blah 3.4" }],
    grouped = [];

data.forEach(function (a) {
    var key = a.id.slice(0, 2);
    if (a.id === key + '00') {
        this[key] = { id: a.id, name: a.name, message: [] };
        grouped.push(this[key]);
    }
    this[key].message.push(a.message);
}, Object.create(null));

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Interesting point about the double Zero issue. I will include that into my code. Your answer is very close to @Nenad Vracar so credit to you as well. I cant seem to get it to work inside my code. I'm getting an error with "message not being defined" on this line: this[key].message.push(a.message); however, I know it works as it works in the Run code snippet window. Thanks for highlighting the double zero issue though. Provisional upvote! – Mr. Benedict Sep 22 '16 at 09:58
  • maybe your data is not sorted by id. if this is the case both proposals does not really work. – Nina Scholz Sep 22 '16 at 10:07