简体   繁体   中英

Best way to check a JS object for matching values

I need to expand(from 2 to a maximum of 10) and optimize some model importing, but i just can't think of a good way to check a javascript object for matching values other than a ton of if statements, So i thought i would ask here and see if there are any experienced js devs that knows of a good, lightweight way to accomplish this..

Basic structure:

//a is the object, it contains some basic, unrelated information and
//either 2, 6 or 10 id's & id2's
//unused id's have a value of 0.
//Sorry for the faulty variables, i was in a rush and just needed to show that xid & xid2 fit together and yid & yid2 fit together, etc.
//input 1
a.1Id = x; //Primary, Desides the actual model to import
a.1Id2 = y; //Secondary, Desides version of the model, specific colours, features, etc
//input 2
a.2Id = z;
a.2Id2 = x;

(up to a maximum of 10 inputs, a.10Id & Id2)

Now, i need to check for matches..

If 1Id is the same as 2Id and 1Id2 is the same as 2Id2, only import the model once.

When there are only two model inputs, it's rather simple.

//the import is not actually structured as var importX, 
//they are pushed to another object and then the loader loads each of them with a for..loop
if (a.1Id === a.2Id && a.1Id2 === a.2Id2){
  var import1 = a.1Id;
  var import12 = a.1Id2;
} else {
  var import1 = a.1Id;
  var import12 = a.1Id2;
  var import2 = a.2Id;
  var import22 = a.2Id2;
}

But beyond that, you can imagine that it starts getting rather heavy with if statements to check how many and if any of them are the same..

So to wrap it up, i'm basicly hoping that it is possible with some kind of function or algorythm, to check all xId and xId2 input values if they are matching with any of the others and then only send one of the matching inputs to the loader, thus avoiding importing the same model several times.

There are a lot of questions left unanswered, so here is something that compares each Id[n] against the next Id[n+1]. It doesn't completely solve the problem, but should point you in the right direction.

I had to change your object, because object properties can't start with a number. I also made some assumptions, such as the values are actually strings (because as you present them in your sample, they are actually variables).

var a = {
  Id1_: '1',
  Id1_2: '1a',
  Id2_: '1',
  Id2_2: '2a',
  Id3_: '3',
  Id3_2: '3a',
  Id4_: '1',
  Id4_2: '1a',
  Id5_: '2',
  Id5_2: '2a',
  Id6_: '3',
  Id6_2: '3a',
  Id7_: '2',
  Id7_2: '2a',
  Id8_: '3',
  Id8_2: '3a',
  Id9_: '1',
  Id9_2: '1a',
  Id10_: '1',
  Id10_2: '2a'
};

The first thing I do is the Object.keys from a because that will allow me to iterate through all the keys without knowing ahead of time what they may be.

var k1 = Object.keys(a);

I then pass the object and the keys into a function:

checkMatches(k1, a);

The function checks the object sequentially, comparing the first key to the second key, second key to the third key, and so on - pushing anything key that doesn't match the other in an array. I console.log the keys involved in each comparison. Here is the function.

function checkMatches(k, o){
  var results = [];
  var s = "Id", f = "_";
  var nextId = 2;
  var idCnt = 0;
  var propt = "";
  for (var i = 0; i < k.length; i++){ 
    idCnt += 1;
    if (idCnt === 3) {
      idCnt = 1;
      nextId += 1;
    }

    propt = s + nextId + f;

    if (idCnt === 2) {
      propt += "2";    
    } 

    console.log(k[i] + ": " + o[k[i]] + " vs " + propt + ": " + o[propt]);
    if (o[k[i]] !== o[propt]) {
      results.push({ id: k[i], value: o[k[i]] });
    }
  } 
  return results;
}

Like I said, it doesn't solve your problem exactly - mostly because there are a lot of specifics that could change the final result.

Here is a jsbin with it working as outlined.

It sounds to me like you're looking simply to put your insertions into an array, and loop over the array each time. That will let you grow to any size, without the if statements getting out of hand.

It would basically look like this:

var imported = [];

var processImport = function (obj) {
  // there are better ways, but this will work:
  var found = false;
  for (var i = 0; i < imported.length; ++i) {
    if (imported[i].id == obj.id && imported[i].id2 == obj.id2) {
      found = true;
      break;
    }
  }
  if (!found) {
    imported.push({
      id: obj.id,
      id2: obj.id2
    });
  }
}

Maybe you're looking for something else, but based on the code you provided, this may be helpful.

Good luck!

 var imported = []; var processImport = function (obj) { // there are better ways, but this will work: var found = false; for (var i = 0; i < imported.length; ++i) { if (imported[i].id == obj.id && imported[i].id2 == obj.id2) { found = true; break; } } if (!found) { imported.push({ id: obj.id, id2: obj.id2 }); } } var toImport = [{ id: 1, id2: 1 }, { id: 1, id2: 2 }, { id: 2, id2: 1 }, { id: 1, id2: 1 }]; for (var j = 0; j < toImport.length; ++j) { processImport(toImport[j]); } alert(imported.length); 

Final result.

//Models.
var mIds = []; //Store id's to import

function Model() {
  this.Id = 0;
  this.Id2 = 0;
}

function newModel(data) {

  var found = false;
  for (var i = 0; i < mIds.length; i++) {
    if (mIds[i].Id === data.Id && mIds[i].Id2 === data.Id2) {
      found = true;
      break;
    }
  }
  if (!found) {
    var model = new Model();
    model.Id = data.Id;
    model.Id2 = data.Id2;

    mIds.push( model );
  }


};

Models are imported in sets of 2, 6 or 10.

As previously mentioned "a" contains some other informations than just id's/id2's, I would have liked to use @whipdancer 's code to handle sending the id's to the newModel function but I had to handle it like this, otherwise it would require rewrites of my code that creates "a",which i am not interested in, and it's maximum 10 models anyhow, so i suppose this is Ok.

if (a.count > 1) { //atleast 2 models
  var data1 = {};
  data1.Id = a.Id1;
  data1.Id2 = a.Id1_2;
  newModel(data1);
  var data2 = {};
  data2.Id = a.Id2;
  data2.Id2 = a.Id2_2;
  newModel(data2);

  //delete data1;
  //delete data2;
}
if (a.count > 5) { //atleast 6 models
  var data3 = {};
  data3.Id = a.Id3;
  data3.Id2 = a.Id3_2;
  newModel(data3);

  var data4 = {};
  data4.Id = a.Id4;
  data4.Id2 = a.Id4_2;
  newModel(data4);

  var data5 = {};
  data5.Id = a.Id5;
  data5.Id2 = a.Id5_2;
  newModel(data5);

  var data6 = {};
  data6.Id = a.Id6;
  data6.Id2 = a.Id6_2;
  newModel(data6);

}
if (a.count > 9) { //10 models
  var data7 = {};
  data7.Id = a.Id7;
  data7.Id2 = a.Id7_2;
  newModel(data7);

  var data8 = {};
  data8.Id = a.Id8;
  data8.Id2 = a.Id8_2;
  newModel(data8);

  var data9 = {};
  data9.Id = a.Id9;
  data9.Id2 = a.Id9_2;
  newModel(data9);

  var data10 = {};
  data10.Id = a.Id10;
  data10.Id2 = a.Id10_2;
  newModel(data10);

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM