-3

I DON'T WANT ONLY DELETE DUPLICATED. I WANT TO MERGE DUPLICATED AND THEN DELETE

this is my test array:

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

and result must be this:

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

flow is next > I have items that may have duplicated. if item's ID's is equal tu other, I mean if ID is duplicated then TEXT fild must be merged into one and duplicated must be deleted and must stay unique with text field, eg. text: "[text1] [text2] [text3] [text4]" this is my old question Merge duplicated items in array but written answers only work for 2 duplicates.

this code is what I try but it only work 2 duplicates, maybe I have 3 or more duplicates this code don't work

arr.forEach(function(item, idx){   

   //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) {

        //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 this duplicate item
         arr.splice(i, 1);
      }      
   }

 });
Community
  • 1
  • 1

3 Answers3

0

Is this what you want?

function merge(a) {
    var newA = [];

    a.forEach(function(o) {
        var index;

        if (newA.some(function(x, i) {
            index = i;
            return x.id === o.id;
        })) {
          if (!/\[|\]/.test(newA[index].text)) {
            newA[index].text = newA[index].text.replace(/^(.*)$/g, "[$1]")
          }
            newA[index].text += "[" + o.text + "]";
            newA[index].text = newA[index].text.replace(/\]\[/g, "] [");
        } else {
          newA.push({
            id: o.id,
            text: o.text.replace(/^(.*)$/g, "[$1]")
          });
        }
    });

  newA.forEach(function(a) {
    if (!/ /g.test(a.text)) {
       a.text = a.text.replace(/\[|\]/g, "");
    }
  });

  return newA;
}
Sebastien Daniel
  • 4,649
  • 3
  • 19
  • 34
0

Both version work with an temporary object for the reference to the item with the id.

The in situ version changes the array and deleted the double items.

The other version builds a new array and adds the text to the appropriate property.

An in situ version.

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

while (i < arr.length) {
    if (!reference[arr[i].id]) {
        reference[arr[i].id] = arr[i];
        i++;
        continue;
    }
    r = reference[arr[i].id];
    if (r.text[0] !== '[') {
        r.text = '[' + r.text + ']';
    }
    r.text += ' [' + arr[i].text + ']';
    arr.splice(i, 1);
}
document.write('<pre>' + JSON.stringify(arr, 0, 4) + '</pre>');

This solution returns a new array:

var arr = [{ id: 1, text: 'ab' }, { id: 1, text: 'cd' }, { id: 2, text: 'other' }, { id: 3, text: 'afafas' }, { id: 1, text: 'test' }, { id: 4, text: 'asfasfa' }],
    result = arr.reduce(function (r, a) {
        if (!r.obj[a.id]) {
            r.obj[a.id] = { id: a.id, text: '' };
            r.array.push(r.obj[a.id]);
        }
        if (r.obj[a.id].text === '') {
            r.obj[a.id].text = a.text;
        } else {
            if (r.obj[a.id].text[0] !== '[') {
                r.obj[a.id].text = '[' + r.obj[a.id].text + ']';
            }
            r.obj[a.id].text += ' [' + a.text + ']';
        }

        return r;
    }, { array: [], obj: {} }).array;

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

In the following example, I have converted values to object and then to array. If your ID can be string, I'd recommend you to use object and not array. This will save you trouble of looping again to fetch data.

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

var _temp = {};
var final = [];
arr.forEach(function(item){
  if(!_temp[item.id])
    _temp[item.id] = [];
  _temp[item.id].push(item.text);
});

Object.keys(_temp).forEach(function(k){
  var val = "";
  if(_temp[k].length>1){
    val = "[ " + _temp[k].join(" ] [ ") + " ]";
  }
  else
    val = _temp[k][0];
  
  final.push({
    id:k,
    text: val
  });
});

console.log("Object: ", _temp);
console.log("Array of Objects: ", final)
Rajesh
  • 24,354
  • 5
  • 48
  • 79