Amiga500
Amiga500

Reputation: 6131

Filtering an array of objects - several criteria

I have an array of objects, like this:

var data = [
        {
            name: "block",
            sameid: 500,
            parentid: 62
        },
        {
            name: "circle",
            sameid: 500,
            parentid: 62
        },
        {
            name: "cube",
            sameid: 500,
            parentid: 62
        }            
    ]

I need to make a filter on that array to remove objects that have sameid and same parentid. But here is a twist that bothers me... If I get this array of objects:

 var data = [
        {
            name: "block",
            sameid: 500,
            parentid: 62
        },
        {
            name: "circle",
            sameid: 500,
            parentid: 62
        },
        {
            name: "cube",
            sameid: 500,
            parentid: 62
        },
        {
            name: "grain",
            sameid: 500,
            parentid: 63
        }
    ]

You can see that object with name grain (last one), it has different parentid. if that is the case, then nothing should be removed.

I am breaking my head around this one. First criteria that I must take into account is a sameid. I should group them by it. Then somehow check for parent ids.

The array can contain many different sameid's and parentid's

UPDATE: In the first case, where the data has three objects. All should be removed, becouse all of them have same sameid and parentid.

In the second case, where the data has four objects all four should be preserved, since there is one different object with different parentid.

UPDATE Desired result:

 var filteredObjects = [];
     data = [
        {
            name: "block",
            sameid: 500,
            parentid: 62
        },
        {
            name: "circle",
            sameid: 500,
            parentid: 62
        },
        {
            name: "cube",
            sameid: 500,
            parentid: 62
        },
        {
            name: "grain",
            sameid: 500,
            parentid: 63
        }
    ]

In this case, filteredObject will have all values, since there is one different parentid:

filteredObjects [{
        name: "block",
        sameid: 500,
        parentid: 62
    },
    {
        name: "circle",
        sameid: 500,
        parentid: 62
    },
    {
        name: "cube",
        sameid: 500,
        parentid: 62
    },
    {
        name: "grain",
        sameid: 500,
        parentid: 63
    }]

In this case:

var filteredObjects = [];
     data = [
        {
            name: "block",
            sameid: 500,
            parentid: 62
        },
        {
            name: "circle",
            sameid: 500,
            parentid: 62
        },
        {
            name: "cube",
            sameid: 500,
            parentid: 62
        }            
    ]

filteredObject will have no values. The data array can contain different sameid as well.

Upvotes: 1

Views: 113

Answers (6)

Nina Scholz
Nina Scholz

Reputation: 386578

You could build a tree with sameid and parentid. Then filter the items and return only the one who have two or more parenid.

function filter(array) {
    var hash = {};
    array.forEach(function (a) {
        hash[a.sameid] = hash[a.sameid] || {};
        hash[a.sameid][a.parentid] = true;
    });
    return array.filter(function (a) {
        return Object.keys(hash[a.sameid]).length > 1;
    });
}

var data0 = [{ name: "block", sameid: 500, parentid: 62 }],
    data1 = [{ name: "block", sameid: 500, parentid: 62 }, { name: "circle", sameid: 500, parentid: 62 }, { name: "cube", sameid: 500, parentid: 62 }],
    data2 = [{ name: "block", sameid: 500, parentid: 62 }, { name: "circle", sameid: 500, parentid: 62 }, { name: "cube", sameid: 500, parentid: 62 }, { name: "grain", sameid: 500, parentid: 63 }],
    data3 = [{ name: "block", sameid: 500, parentid: 62 }, { name: "circle", sameid: 500, parentid: 62 }, { name: "cube", sameid: 500, parentid: 62 }, { name: "grain", sameid: 500, parentid: 63 }, { name: "library", sameid: 600, parentid: 66 }, { name: "wood", sameid: 600, parentid: 66 }, { name: "water", sameid: 700, parentid: 77 }, { name: "fire", sameid: 700, parentid: 78 }, { name: "orphan", sameid: 300, parentid: 12 }];

console.log(filter(data0));
console.log(filter(data1));
console.log(filter(data2));
console.log(filter(data3));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 3

Dhananjaya Kuppu
Dhananjaya Kuppu

Reputation: 1322

You may also look into this approach:

data.reduce(function(p, c, index){           
    if (p.length !== index) return [];                              

    if (p.length === 0) {
        return p.concat(c);
    }
    else if (p[0].sameid === c.sameid && p[0].parentid === c.parentid){                              
           return p.concat(c); 
     }           

      return [];
    }, []);

Upvotes: 0

mayank
mayank

Reputation: 460

i have tried to solve your question , you need to add underscorejs for the following code.

var data2 = [
    {
        name: "block",
        sameid: 500,
        parentid: 62
    },
    {
        name: "circle",
        sameid: 500,
        parentid: 62
    },
    {
        name: "cube",
        sameid: 500,
        parentid: 62
    },
    {
        name: "grain",
        sameid: 500,
        parentid: 63
    }
]

var backup = data2;
var count1 = 0; 
var count2 = 0;
for(var i = 0; i< data2.length ;i ++){
  for(var j = i+1;j<data2.length ;j++){
    if(data2[i].sameid == data2[j].sameid && data2[i].parentid == data2[j].parentid){
      count1++;
    }
    else if((data2[i].sameid == data2[j].sameid && data2[i].parentid != data2[j].parentid) ||(data2[i].sameid != data2[j].sameid && data2[i].parentid == data2[j].parentid) ){
      count2++;
    }

  }
  if(count2 == 0 && count1 != 0){
    backup = _.reject(backup,function(d){return d.sameid == data2[i].sameid && d.parentid == data2[i].parentid   })
  }
  count2=0;count1=0;

}


console.log(backup,"my new array")

Upvotes: 0

you can try this

var distincts = []
for (var i = 0; i < data.length; i++)
    if (distincts.indexOf(data[i].sameid)==-1)
      distincts.push(data[i].sameid);

if(distincts.length==1){
    var distinctp = []
    for (var i = 0; i < data.length; i++)
        if (distinctp.indexOf(data[i].sameid)==-1)
           distinctp.push(data[i].sameid);
    if(distincts.length==1){
       data.splice(0,data.length)
    }
}

Upvotes: 0

Yeldar Kurmangaliyev
Yeldar Kurmangaliyev

Reputation: 34189

You can simply iterate through your initial array and build a new one while checking the uniqueness.
It can be done by utilizing Array.prototype.filter:

var data = [
  {
    name: "same sameid and parentid",
    sameid: 500,
    parentid: 62
  },
  {
    name: "same sameid and parentid",
    sameid: 500,
    parentid: 62
  },
  {
    name: "different sameid, same parentid",
    sameid: 501,
    parentid: 62
  },
  ,
  {
    name: "same sameid, different parentid",
    sameid: 500,
    parentid: 63
  }
];

var set = {};
var newData = data.filter(function(x) {
  var key = x.sameid + "_" + x.parentid;
  
  if (set[key]) 
    return false;
  
  return (set[key] = true);
});

console.log(newData);

Note that this algorithm takes every first occurence of same IDs. You can implement another logics, if you need.

Upvotes: 2

Madara&#39;s Ghost
Madara&#39;s Ghost

Reputation: 174957

You can use ES2015's Set structure to find out whether or not you have more than one kind:

const parentIdSet = new Set(data.map(item => item.parentid));
console.log(parentIdSet.size); 
// If 1, you only have one parentId in the entire dataset.

A Set is a collection of unique values. By putting all of the parent IDs into a Set, all of the duplicate values are removed, and you have only unique values left. If the size of the Set is 1, it means that you only have one parentid in the entire dataset.

Using a set means you can avoid having to store the initial values somewhere and try to compare. The Set does it for you automatically, and with better performance (probably)

Upvotes: 2

Related Questions