Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing elements with conditions from an array of objects

Tags:

javascript

Let's call reversed what {"src":"A", "target":"B"} is to {"src":"B", "target":"A"}. As a first step I want to remove all reversed objects from the array. My code right below is not giving me the expected result.

var reducedArr = [
   {"src":"A", "target":"B", "val":"15"},
   {"src":"A", "target":"C", "val":"11"},
   {"src":"B", "target":"A", "val":"9"},
   {"src":"C", "target":"A", "val":"5"},
   {"src":"C", "target":"B", "val":"18"},
   {"src":"B", "target":"A", "val":"19"}
]

var result= reducedArr

result.forEach(element => {

  r = reducedArr.find(e => {return (e.src == element.target && e.target == element.src)});
  if(r){
    reducedArr = reducedArr.filter(ee => ee !== r)
    console.log(reducedArr)
  }
});

The proper result should be :

[
   {"src":"A", "target":"B", "val":"15"},
   {"src":"A", "target":"C", "val":"11"},
   {"src":"C", "target":"B", "val":"18"},
]

Once I figure that out, I would like to add a condition where between the object and it's reversed version, I would keep the one that has the highest value for "val". So the ideal final result would be :

[
   {"src":"A", "target":"C", "val":"11"},
   {"src":"C", "target":"B", "val":"18"},
   {"src":"B", "target":"A", "val":"19"}
]

like image 356
JK2018 Avatar asked Dec 06 '25 17:12

JK2018


2 Answers

In the reduce() callback, you can use findIndex() to check if you have already accumulated the reverse element, and splice() the new element in if the value is higher.

const array = [
  {"src":"A", "target":"B", "val":"15"},
  {"src":"A", "target":"C", "val":"11"},
  {"src":"B", "target":"A", "val":"9"},
  {"src":"C", "target":"A", "val":"5"},
  {"src":"C", "target":"B", "val":"18"},
  {"src":"B", "target":"A", "val":"19"}
];

const result = array.reduce((a, v1) => {
  const i = a.findIndex(v2 => v1.src === v2.target && v1.target === v2.src);
  
  if (i < 0) {
    a.push(v1);
  } else if (+a[i].val < +v1.val) {
    a.splice(i, 1, v1);
  }
  
  return a;
}, []);

console.log(result);
like image 175
Robby Cornelissen Avatar answered Dec 08 '25 06:12

Robby Cornelissen


Robby has given a great approach. However, I have a slight different version of this solution.

  • This solution checks for Duplicate item as well. So in the above case, we do have item having same src, and target, but having different val. For example:
[
  {"src":"B", "target":"A", "val":"9"},
  {"src":"B", "target":"A", "val":"19"}
]
  • So it checks, compares and submit the data which is preferred as per the question.

Algorithm:

1. Run through the given array
2. Keep another array for storing the final result
3. Check whether the final result array has something already stored. If not stored, push the item
4. If there are items, then check for the duplicate or reversed item:
   4(i) If there are not duplicate or reverse item found, simply add it to the final result array
   4(ii) If found, then compare the current val and the founded item's val.
        4(ii)(i) If the current val is greater than the founded one, replace it with the current object in the final array
        4(ii)(ii) If not, then keep the current object in the final result array
5. Once the loop is finished, then return the result or console

const reducedArr = [
    {"src":"A", "target":"B", "val":"15"},
    {"src":"A", "target":"C", "val":"11"},
    {"src":"B", "target":"A", "val":"9"},
    {"src":"C", "target":"A", "val":"5"},
    {"src":"C", "target":"B", "val":"18"},
    {"src":"B", "target":"A", "val":"19"}
];

// To store the expected outcome, which is objects having no reversed
// item and having the maximum val in the object compared from their reversed ones
let resultArray = [];

// Looping through every item to add the item into the new array
reducedArr.forEach((item, index) => {
    // Simply push the item
    if(resultArray.length === 0){
        resultArray.push(item);
    }else{
      // Reverse Foundation. Checks for Duplicate items as well
      const reverseFoundDataIndex = resultArray
      .findIndex(data => (data.src === item.src && data.target === item.target) || (data.target === item.src && data.src === item.target));
      
      // If not found, simply push, because no reverse data is there
      if(reverseFoundDataIndex === -1) resultArray.push(item);
      else{
        // Founding the maximum value via comparing with the resultArray items and the current item in the given array
        if(parseInt(item.val) > parseInt(resultArray[reverseFoundDataIndex].val))
            // If found one, replacing it with the maximum one
            resultArray[reverseFoundDataIndex] = item;
      }
    }
});

// Sorting based upon the val given in the result array, else, you can do only sort as well
console.log(resultArray
.sort((firstItem, secondItem) => firstItem.val - secondItem.val));

Important Key Take Aways:

  • parseInt()
  • Array.prototype.sort()
  • Array.prototype.findIndex()
like image 40
Alok Avatar answered Dec 08 '25 05:12

Alok