Billal BEGUERADJ
Billal BEGUERADJ

Reputation: 22804

Original array changed without any modifications done

I am trying to remove duplicate objects from an array, and keep only the objects which have the highest nb value.

Example:

From this array:

let arr = [
      {id: 1, nb: 1},
      {id: 1, nb: 4},
      {id: 2, nb: 1},
      {id: 3, nb: 1},
      {id: 1, nb: 2},
      {id: 1, nb: 3},
      {id: 2, nb: 7},
      {id: 2, nb: 8},
    ];

I am supposed to get this:

arr2 = [
   { id: 1, nb: 4 },
   { id: 2, nb: 8 }, 
   { id: 3, nb: 1 }
]

The algorithm below is very correct in theory, however I see the original array is modified by the end (see the last console.log(arr) below):

Code:

let arr = [
  {id: 1, nb: 1},
  {id: 1, nb: 4},
  {id: 2, nb: 1},
  {id: 3, nb: 1},
  {id: 1, nb: 2},
  {id: 1, nb: 3},
  {id: 2, nb: 7},
  {id: 2, nb: 8},
];
// Original array
console.log(arr);

let tmp = {};
for(let i=0; i<arr.length; i++) {
  if( !tmp[arr[i].id] ) {
    tmp[arr[i].id] = arr[i];     
  } else {
    if (tmp[arr[i].id].nb < arr[i].nb ) {
      tmp[arr[i].id].nb = arr[i].nb;
    }
  }     
}

var result = Object.values(tmp);
// This output the desired result
console.log(result);
// Why the original array changed ?
console.log(arr);

This will output:

> Array [Object { id: 1, nb: 1 }, Object { id: 1, nb: 4 }, Object { id: 2, nb: 1 }, Object { id: 3, nb: 1 }, Object { id: 1, nb: 2 }, Object { id: 1, nb: 3 }, Object { id: 2, nb: 7 }, Object { id: 2, nb: 8 }]
> Array [Object { id: 1, nb: 4 }, Object { id: 2, nb: 8 }, Object { id: 3, nb: 1 }]
> Array [Object { id: 1, nb: 4 }, Object { id: 1, nb: 4 }, Object { id: 2, nb: 8 }, Object { id: 3, nb: 1 }, Object { id: 1, nb: 2 }, Object { id: 1, nb: 3 }, Object { id: 2, nb: 7 }, Object { id: 2, nb: 8 }]

Why did the original array changed when there is no processing on it apart from looping?

Upvotes: 0

Views: 99

Answers (2)

amrender singh
amrender singh

Reputation: 8239

The original array is updated at last as the objects in your tmp map and arr share the same object reference. So changes made in tmp will be reflected in arr. You can use Object.assign() to make them point to separate reference. Try the following:

let arr = [ {id: 1, nb: 1}, {id: 1, nb: 4}, {id: 2, nb: 1}, {id: 3, nb: 1}, {id: 1, nb: 2}, {id: 1, nb: 3}, {id: 2, nb: 7}, {id: 2, nb: 8}, ];


let tmp = {};
for(let i=0; i<arr.length; i++) {
  if( !tmp[arr[i].id] ) {
    tmp[arr[i].id] = Object.assign({},arr[i]);     
  } else {
    if (tmp[arr[i].id].nb < arr[i].nb ) {
      tmp[arr[i].id].nb = arr[i].nb;
    }
  }     
}

var result = Object.values(tmp);
console.log(result)

Upvotes: 2

Nikhil Aggarwal
Nikhil Aggarwal

Reputation: 28475

Because objects in both the arrays are sharing the same reference.

You will need to update from

tmp[arr[i].id] = arr[i];

to

tmp[arr[i].id] = JSON.parse(JSON.stringify(arr[i]));

let arr = [
  {id: 1, nb: 1},
  {id: 1, nb: 4},
  {id: 2, nb: 1},
  {id: 3, nb: 1},
  {id: 1, nb: 2},
  {id: 1, nb: 3},
  {id: 2, nb: 7},
  {id: 2, nb: 8},
];

let tmp = {};
for(let i=0; i<arr.length; i++) {
  if( !tmp[arr[i].id] ) {
    tmp[arr[i].id] = JSON.parse(JSON.stringify(arr[i]));     
  } else {
    if (tmp[arr[i].id].nb < arr[i].nb ) {
      tmp[arr[i].id].nb = arr[i].nb;
    }
  }     
}

var result = Object.values(tmp);
console.log(arr); // original array unchanged

Upvotes: 1

Related Questions