Remove objects from an array of objects in JavaScript based on two conditions (Duplicate mac address & using condition less than or greater than)

Viewed 94

I want to remove objects from array with the same mac address based on RSSI value, whether one value is greater than the other one.

For example,

 values = [{
    mac: 'AC233F271F7E',
    rssi: '-60',
  }, {
    mac: 'AC233F271F80',
    rssi: '-65',
  }, {
    mac: 'AC233F271F7E',
    rssi: '-55',
  }, {
    mac: 'AC233F2AFB37',
    rssi: '-70',
 }]

How can I remove the object based on duplicate mac address, not only that, but also remove the one with smaller RSSI value. So the end result will look like this,

  values = [{
    mac: 'AC233F271F80',
    rssi: '-65',
  }, {
    mac: 'AC233F271F7E',
    rssi: '-55',
  }, {
    mac: 'AC233F2AFB37',
    rssi: '-70',
 }]

I have been looking for many solutions on how to remove duplicate objects in StackOverflow based on conditions. However, all of the solutions I had found remove the objects based on the similarity, for example, like this code below, it removes the object based on duplicate place and name. But I want something that can remove duplicate object when one of the RSSI values is greater than the other.

things.thing = things.thing.filter((thing, index, self) =>
  index === self.findIndex((t) => (
    t.place === thing.place && t.name === thing.name
 ))
)

I also tried this code but it only removes duplicate object based on mac address only.

    var i;
    var obj = {};
    var len=vm.allbeacons.length

    for (  i=0; i < len; i++ ){
        obj[vm.allbeacons[i]['mac']] = vm.allbeacons[i];

    }

    vm.allbeacons= new Array();
    for ( var key in obj )
    {   vm.allbeacons.push(obj[key]);

    } 

I expected a code that can remove objects with the same mac address and also based on RSSI value, whether one value is greater than the other one. Thank you very much in advance if you can help me, really appreciate it!

3 Answers

Reduce into an object indexed by MAC address, whose values are the largest found so far (which you can calculate with Math.max). Then transform the object back into an array with Object.entries:

const values = [{
  mac: 'AC233F271F7E',
  rssi: '-60',
}, {
  mac: 'AC233F271F80',
  rssi: '-65',
}, {
  mac: 'AC233F271F7E',
  rssi: '-55',
}, {
  mac: 'AC233F2AFB37',
  rssi: '-70',
}];

const obj = values.reduce((a, { mac, rssi }) => {
  a[mac] = a[mac] ? Math.max(a[mac], rssi) : rssi;
  return a;
}, {});
const output = Object.entries(obj).map(([mac, rssi]) => ({ mac, rssi: String(rssi) }));
console.log(output);

If you want to keep the array objects together (and this keep other properties in the objects), then change the accumulator's object's values to those objects, rather than just the rssi number:

const values = [{
  mac: 'AC233F271F7E',
  rssi: '-60',
  foo: 5
}, {
  mac: 'AC233F271F80',
  rssi: '-65',
  foo: 6
}, {
  mac: 'AC233F271F7E',
  rssi: '-55',
  foo: 7
}, {
  mac: 'AC233F2AFB37',
  rssi: '-70',
  foo: 8
}];

const accumObj = values.reduce((a, obj) => {
  if (!a[obj.mac] || Number(a[obj.mac].rssi) < Number(obj.rssi)) {
    a[obj.mac] = obj;
  }
  return a;
}, {});
const output = Object.values(accumObj);
console.log(output);

You could take a hash table and check the rssi.

var values = [{ mac: 'AC233F271F7E', rssi: '-60' }, { mac: 'AC233F271F80', rssi: '-65' }, { mac: 'AC233F271F7E', rssi: '-55' }, { mac: 'AC233F2AFB37', rssi: '-70' }],
    result = Object.values(values.reduce((r, o) => {
        if (!r[o.mac] || +r[o.mac].rssi < +o.rssi) r[o.mac] = o;
        return r;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

If backwards compatibility with older browsers is an issue, then a simple nested loop seems the best solution.

Most browsers supports the features used in other answers, so this is only if you need older browsers like Internet Explorer or the like.

var values = [{
        mac: 'AC233F271F7E',
        rssi: '-60'
    }, {
        mac: 'AC233F271F80',
        rssi: '-65'
    }, {
        mac: 'AC233F271F7E',
        rssi: '-55'
    }, {
        mac: 'AC233F2AFB37',
        rssi: '-70'
    }];
//Log initial values
console.log("Initial values");
console.log(values);
function RemoveDuplicatesKeepLargerRSSI(list) {
    for (var index1 = 0; index1 < list.length; index1++) {
        var obj1 = list[index1];
        for (var index2 = index1 + 1; index2 < list.length; index2++) {
            var obj2 = list[index2];
            //If same mac adress
            if (obj1.mac === obj2.mac) {
                //numeric compare rssi
                if (parseInt(obj1.rssi, 10) < parseInt(obj2.rssi, 10)) {
                    //remove from outer loop and break inner cycle
                    list.splice(index1, 1);
                    break;
                }
                else {
                    //remove from inner loop and offset index
                    list.splice(index2, 1);
                    index2--;
                }
            }
        }
    }
    return list;
}
//Log modified values
console.log("Modified values");
console.log(RemoveDuplicatesKeepLargerRSSI(values));

Related