1

How do I most efficiently structure a "conditions" object to find matches within a list of objects (consisting of key value pairs) and add them to a list of "matches?

I have a the following testList that contains multiple objects:

var testList = {
  "A": "SUBA1",
  "B": "SUBB2",
  "C": "SUBC5",
},
{
  "A": "SUBA2",
  "B": "SUBB3",
  "C": "SUBC1",
}
...
]

Right now my matchCondition with one condition is simple focused on one key and value:

var matchCondition = {"key": "A", val:"SUBA1"};

I want to shove any individual object in testList that matches my "matchCondition" into the "matchedList".

var matchedList = [];

So I do this now using "findMatches" function:

function findMatches(matchCondition, testList) {
var matchedList = [];
for(var i = 0; i < testList.length; i++) {
   if(testList[matchCondition[key]] == testList[i][matchCondition[val]]) {
       matchedList.push(testList[i]);
   }
}
return matchedList;
}

My problem is, what if I want to match using multiple conditions something where for example "A" could be equal to "SUBA1" or "SUBA2", AND "B" is "SUBB2", AND "C" is "SUBB5":

Maybe the object could look like this?

var matchCondition = {
  "A": ["SUBA1", "SUBA2"],
  "B": ["SUBB2"],
  "C": ["SUBC5"]
}

I am not sure what is the best way I can update my findMatches function to be more robust... or how do I best structure my "matchCondition" to be able to support multiple key values I want to match?

Rolando
  • 58,640
  • 98
  • 266
  • 407

3 Answers3

0

You can iterate the mach condition object hasOwnProperty() and check its value meets the requirement.

var testList = [{
  "A": "SUBA1",
  "B": "SUBB2",
  "C": "SUBC5",
}, {
  "A": "SUBA2",
  "B": "SUBB3",
  "C": "SUBC1",
}];

var matchCondition = {
  "A": ["SUBA1", "SUBA2"],
  "B": ["SUBB2"],
  "C": ["SUBC5"]
}

function findMatches(testList, matchCondition) {
 return testList.filter(function(obj){
  for (var key in matchCondition) {
     if (matchCondition.hasOwnProperty(key) && obj.hasOwnProperty(key)) {
     if( matchCondition[key].indexOf(obj[key]) == -1){
    return false;
     }     
     }else{
    return false;
     }
  }
  
  return true
 });
}

snippet.log(JSON.stringify(findMatches(testList, matchCondition)))
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

A good read Javascript iterate object

Community
  • 1
  • 1
Satpal
  • 132,252
  • 13
  • 159
  • 168
0

A proposal with some array methods like Array.prototype.filter() and Array.prototype.every() and Object.keys().

var testList = [{ "A": "SUBA1", "B": "SUBB2", "C": "SUBC5", }, { "A": "SUBA2", "B": "SUBB3", "C": "SUBC1", }],
    matchCondition = { "A": ["SUBA1", "SUBA2"], "B": ["SUBB2"], "C": ["SUBC5"] };

function filter(data, condition) {
    return data.filter(function (a) {
        return Object.keys(condition).every(function (k) {
            return ~condition[k].indexOf(a[k]);
        });
    });
}

document.write('<pre>' + JSON.stringify(filter(testList, matchCondition), 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

It is not clear what you are expecting as a result, but here is a possible ES6 solution; based on your multiple condition matchCondition example.

'use strict';
var testList = [{
  "A": "SUBA1",
  "B": "SUBB2",
  "C": "SUBC5",
}, {
  "A": "SUBA2",
  "B": "SUBB3",
  "C": "SUBC1",
}];
var matchCondition = {
  "A": ["SUBA1", "SUBA2"],
  "B": ["SUBB2"],
  "C": ["SUBC5"]
};
var matchedList = [];

for (let item of testList) {
  let x = Object.create(null);
  for (let key of Object.keys(matchCondition)) {
    let val = item[key];
    if (val) {
      for (let sub of matchCondition[key]) {
        if (sub === val) {
          x[key] = sub;
          break;
        }
      }
    }
  }
  matchedList.push(x);
}
document.getElementById('out').textContent = JSON.stringify(matchedList, null, 2);
console.log(matchedList);
<pre id="out"></pre>

Or similar in ES5

'use strict';
var testList = [{
  "A": "SUBA1",
  "B": "SUBB2",
  "C": "SUBC5",
}, {
  "A": "SUBA2",
  "B": "SUBB3",
  "C": "SUBC1",
}];
var matchCondition = {
  "A": ["SUBA1", "SUBA2"],
  "B": ["SUBB2"],
  "C": ["SUBC5"]
};
var matchedList = testList.reduce(function(acc, item) {
  var x = Object.create(null);
  Object.keys(matchCondition).forEach(function(key) {
    var val = item[key];
    if (val) {
      matchCondition[key].some(function(sub) {
        if (sub === val) {
          x[key] = sub;
          return true;
        }
      });
    }
  });
  acc.push(x);
  return acc;
}, []);
document.getElementById('out').textContent = JSON.stringify(matchedList, null, 2);
console.log(matchedList);
<pre id="out"></pre>

These are not your only possibilities, but you need to be clearer about your expectations and it would be good to see what you have tried, and where you are having a problem.

Xotic750
  • 22,914
  • 8
  • 57
  • 79