2

I have following array of objects.

[{"rId":24,"gId":40,"sId":20,"disabled":false},
 {"rId":24,"gId":40,"sId":19,"disabled":false},
 {"rId":24,"gId":40,"sId":50,"disabled":false},
 {"rId":24,"gId":40,"sId":20,"disabled":true},
 {"rId":24,"gId":40,"sId":19,"disabled":true},
 {"rId":24,"gId":40,"sId":50,"disabled":true},
 {"rId":24,"gId":39,"sId":18,"disabled":false}]

In which some records are antithesis ex. 1st element and 4th which has same rId, gId, and sId but disabled flag is opposite. I want to eliminate all such records.

My expected array is {"rId":24,"gId":39,"sId":18,"disabled":false} (eliminate all antithesis records)

I tried following code but it is giving me wrong output.

arrOfObj=[{"rId":24,"gId":40,"sId":20,"disabled":false},
 {"rId":24,"gId":40,"sId":19,"disabled":false},
 {"rId":24,"gId":40,"sId":50,"disabled":false},
 {"rId":24,"gId":40,"sId":20,"disabled":true},
 {"rId":24,"gId":40,"sId":19,"disabled":true},
 {"rId":24,"gId":40,"sId":50,"disabled":true},
 {"rId":24,"gId":39,"sId":18,"disabled":false}]


$.each(arrOfObj,function (index1,firstObj) {
    $.each(arrOfObj,function (index2,secondObj) {
        if(index1>= index2){
            return true;
        }
        var areObjAntithesis=firstObj.rId===secondObj.rId && firstObj.gId===secondObj.gId
           && firstObj.sId===secondObj.sId && firstObj.disabled!==secondObj.disabled;

        if(areObjAntithesis){
            arrOfObj.splice(index1,1);
            arrOfObj.splice(index2,1)
            return false;
        }
    })
})

Is there any elegant way to achieve expected output ?

5 Answers 5

1

You could do this with map() and filter()

var data = [{"rId":24,"gId":40,"sId":20,"disabled":false},
 {"rId":24,"gId":40,"sId":19,"disabled":false},
 {"rId":24,"gId":40,"sId":50,"disabled":false},
 {"rId":24,"gId":40,"sId":20,"disabled":true},
 {"rId":24,"gId":40,"sId":19,"disabled":true},
 {"rId":24,"gId":40,"sId":50,"disabled":true},
 {"rId":24,"gId":39,"sId":18,"disabled":false}]
 
var ar = data.map(function(e) {
  return e.rId + '|' + e.gId + '|' + e.sId;
});
 
var result = data.filter(function(e) {
  var key = e.rId + '|' + e.gId + '|' + e.sId;
  return ar.indexOf(key) == ar.lastIndexOf(key);
});

console.log(result)

Sign up to request clarification or add additional context in comments.

Comments

0

Use http://underscorejs.org/#where and do like that:

var newArrOfObj=_.where(arrOfObj, {disabled:true});

Comments

0

You can use multiple array.filter and check count and only return elements which have more than 1 value and if values are same or have only one value

var data = [{"rId":24,"gId":40,"sId":20,"disabled":false},
 {"rId":24,"gId":40,"sId":19,"disabled":false},
 {"rId":24,"gId":40,"sId":50,"disabled":false},
 {"rId":24,"gId":40,"sId":20,"disabled":true},
 {"rId":24,"gId":40,"sId":19,"disabled":true},
 {"rId":24,"gId":40,"sId":50,"disabled":true},
 {"rId":24,"gId":39,"sId":18,"disabled":false}]

var result = data.filter(function(outer){
  var disablesValues = []
  
  var _r = data.filter(function(inner){
    if(inner.gId === outer.gId && inner.sId === outer.sId){
      if(disablesValues.indexOf(inner.disabled) < 0)
        disablesValues.push(inner.disabled);
      return true;
    }
  });
  
  return _r.length === 1 || disablesValues.length === 1
});

console.log(result)

Comments

0

Here is functional programming style ES6 solution, which will deal with more repetitions as well, counting how the number of disabled and enabled objects balance annihilate each other:

function eliminateOpposites(arr) {
    return [...arr
        .map( o => ({ o, k: JSON.stringify({ rId:o.rId, gId:o.gId, sId:o.sId }) }) )
        .reduce( (acc, o) => acc.set(o.k, (acc.get(o.k) || 0)+ (+o.o.disabled || -1)),
                             new Map() )]
        .filter( ([k, balance]) => balance )
        .map( ([k, balance]) => Object.assign(JSON.parse(k), {disabled: balance>0}));
}

// Sample data
var arrOfObj=[
 {"rId":24,"gId":40,"sId":20,"disabled":false},
 {"rId":24,"gId":40,"sId":19,"disabled":false},
 {"rId":24,"gId":40,"sId":50,"disabled":false},
 {"rId":24,"gId":40,"sId":20,"disabled":true},
 {"rId":24,"gId":40,"sId":19,"disabled":true},
 {"rId":24,"gId":40,"sId":50,"disabled":true},
 {"rId":24,"gId":39,"sId":18,"disabled":false}]
 
console.log(eliminateOpposites(arrOfObj));

It makes use of hashing, which leads to a O(n) algorithm instead of O(n²), which is the case with indexOf-style solutions.

JSON.stringify and JSON.parse are used to compose and decompose the composite key values. The string version serves as key in a Map, in which each entry logs a count of disabled versus enabled occurrences of the same key. The .filter() call kicks out the cases where the count of disabled and enabled occurrences is the same (could be 2 versus 2), and the final .map() turns the kay/value array back to the expected format.

Comments

0

You could two loops, one for collecting and one for filtering the array.

var data = [{ "rId": 24, "gId": 40, "sId": 20, "disabled": false }, { "rId": 24, "gId": 40, "sId": 19, "disabled": false }, { "rId": 24, "gId": 40, "sId": 50, "disabled": false }, { "rId": 24, "gId": 40, "sId": 20, "disabled": true }, { "rId": 24, "gId": 40, "sId": 19, "disabled": true }, { "rId": 24, "gId": 40, "sId": 50, "disabled": true }, { "rId": 24, "gId": 39, "sId": 18, "disabled": false }],
    hash = Object.create(null),
    getKey = function (o) { return ["rId", "gId", "sId"].map(function (k) { return o[k]; }).join('|'); },
    result;

data.forEach(function (a) {
    var key = getKey(a);
    hash[key] = (hash[key] || 0) + (a.disabled || -1);
});

result = data.filter(function (a) {
    return hash[getKey(a)];
});

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

ES6 with Array#find

var data = [{ "rId": 24, "gId": 40, "sId": 20, "disabled": false }, { "rId": 24, "gId": 40, "sId": 19, "disabled": false }, { "rId": 24, "gId": 40, "sId": 50, "disabled": false }, { "rId": 24, "gId": 40, "sId": 20, "disabled": true }, { "rId": 24, "gId": 40, "sId": 19, "disabled": true }, { "rId": 24, "gId": 40, "sId": 50, "disabled": true }, { "rId": 24, "gId": 39, "sId": 18, "disabled": false }],
    result = data.filter(a =>
        !data.find(b => ["rId", "gId", "sId"].every(k => 
            a[k] === b[k]
        ) && a.disabled !== b.disabled));

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.