-1

I have array and I want to merge duplicated items.

var arr = [{
    'id': 1,
    'text': 'ab'
}, {
    'id': 1,
    'text': 'cd'
}, {
    'id': 2,
    'text': 'other'
}, {
    'id': 3,
    'text': 'afafas'
}, {
    'id': 4,
    'text': 'asfasfa'
}];

var work = arr.reduce(function(p, c) {
    var key = c.id;

    p[key].text.push(c.text);
});

console.log(work);

And output must be like that:

[{
    'id': 1,
    'text': ["[ab] [cd]"]
}, {
    'id': 2,
    'text': 'other'
}, {
    'id': 3,
    'text': 'afafas'
}, {
    'id': 4,
    'text': 'asfasfa'
}]

Here is what I tried but result is fail: ( https://jsfiddle.net/2m7kzkba/

  • 1
    I think this post will help you further [https://stackoverflow.com/questions/23357933/merge-duplicates-in-javascript-array](https://stackoverflow.com/questions/23357933/merge-duplicates-in-javascript-array) It's not exacly what you want but maybe you can use it – Casper Schobers Jan 26 '16 at 15:11
  • @CasperSchobers thank you. I will try and in my opinion it will help me :* – NewUbuntu Developer Jan 26 '16 at 15:15
  • @CasperSchobers it doesn't helped me. when I adding duplicated words in [] it is inserting all data in [] – NewUbuntu Developer Jan 26 '16 at 15:25

3 Answers3

0

Your mistake is to return nothing from your reduce function.

Here is a working code:

var arr = [
  {'id': 1, 'text': 'ab'},
  {'id': 1, 'text': 'cd'},
  {'id': 2, 'text': 'other'},
  {'id': 3, 'text': 'afafas'},
  {'id': 4, 'text': 'asfasfa'},
  {'id': 1, 'text': 'ededed'}
];

var work = arr.reduce(function(acc, item) {

    // row not existing, nothing about this id registered > add only string
    if(!acc[item.id] || !acc[item.id].text) {
      acc[item.id] = {text: item.text};
    }
    // row already an array > add new with []
    else if(acc[item.id].text instanceof Array) {
      acc[item.id].text.push('[' + item.text + ']'); 
    }
    // row existing > create array with existing string and new one
    else {
      acc[item.id] = {
        text: ['[' + acc[item.id].text + ']', '[' + item.text + ']']
      };
    }

    return acc;
}, {});

plunker

bertrandg
  • 3,147
  • 2
  • 27
  • 35
  • Lean more about reduce function in these 2 small videos: https://youtu.be/Wl98eZpkp-c & https://www.youtube.com/watch?v=1DMolJ2FrNY – bertrandg Jan 26 '16 at 15:31
  • this works but merged must be like that, string: [ab][cd] – NewUbuntu Developer Jan 26 '16 at 15:44
  • Sorry @NewUbuntuDeveloper , I read too quickly. I updated my plunker to return what you want: https://plnkr.co/edit/ZdecEU?p=preview I think `reduce` is better than multiple for/foreach loops. – bertrandg Jan 26 '16 at 16:37
0

If you're not averse to using a utility library like Underscore, something like this will work:

function mergeListOfObjects(arr) {
  function objectID(obj) {
    return obj.id;
  }

  function objectText(obj) {
    return obj.text;
  }

  function mergeObject(id) {
    return {id: id, text: _.map(_.where(arr, {id: id}), objectText) }; 
  }

  return _.map(_.uniq(_.map(arr, objectID)), mergeObject);
}

console.log(mergeListOfObjects(arr));

n.b. This doesn't account for the fact that your example output added some extra brackets out of nowhere, i.e., 'text': ["[ab]", "[cd]"]. I think the output you wanted is more like 'text': ["ab", "cd"].

Jezen Thomas
  • 13,619
  • 6
  • 53
  • 91
  • here is an error: "Uncaught ReferenceError: _ is not defined" and I want with brackets. exectly like this: 'text': ["[ab]", "[cd]"] and string will be this: [ab][cd] – NewUbuntu Developer Jan 26 '16 at 15:43
  • Yeah. You need to include the Underscore library. If you need square brackets inside your strings, add a function that wraps a string in square brackets and apply that function to each array element when the length of a `text` array is greater than one. – Jezen Thomas Jan 26 '16 at 15:46
0

Here is a plain approach using two nested iterators

We would be iterating through the array and see if duplicate items are there by nested iterating per item. We mark duplicate items and would delete them later.

Plunker

arr.forEach(function(item, idx){   

  //Do not iterate if it is marked
  if (typeof item.marked !== 'undefined')
        return;

   //Now lets go throug it from the next element
   for (var i = idx + 1; i < arr.length; i++) {

     //Check if the id matches
     if (item.id === arr[i].id) {

        //Mark
        arr[i].marked = true;

        //If the text field is already an array just add the element        
        if (arr[idx].text.constructor === Array) {
            arr[idx].text.push('[' + arr[i].text + ']');   
         }
         else {  //Create an array if not
            arr[idx].text = new Array('[' + arr[idx].text + ']', '[' + arr[i].text + ']');
         }

      }      
   }

 });


//Delete marked items now
for (var i = arr.length - 1; i >= 0; i--) {
   if (typeof arr[i].marked !== 'undefined')
      arr.splice(i, 1);
 }
Charlie
  • 22,886
  • 11
  • 59
  • 90