1
const conditionalArray = [
  { name: "line", condition: ">=", value: 5 },
  { name: "revene", condition: "in", value: 6 },
];

const dataTofilter = [
  { line: 3, revene: 4, sale: 3, fridge: "lg" },
  { line: 6, revene: 3, sale: 2, fridge: "samsung" },
];

I have these 2 arrays one is having conditions ( many more can be there) and second is to filter

Final result should be [{ line: 6, revene: 3, sale: 2, fridge: "samsung" }]

Singla
  • 39
  • 5
  • 1
    Familiarize yourself with [how to access and process nested objects, arrays or JSON](/q/11922383/4642212) and use the available static and instance methods of [`Object`](//developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object#Static_methods) and [`Array`](//developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array#Static_methods). – Sebastian Simon Aug 17 '21 at 18:01
  • @Behemoth Can you please let me know how to filter using conditional array – Singla Aug 17 '21 at 18:06
  • What is `{ name: "revene", condition: "in", value: 6 }` supposed to mean? `revene in 6` is invalid syntax. – Sebastian Simon Aug 18 '21 at 17:31
  • @Sebastian instead of 6 some string revene in (‘abc’) – Singla Aug 18 '21 at 17:33
  • Ah, okay, so `in: (a, b) => b.includes(a)` or similar as a function property in the approach below, right? The question still says `value: 6` instead of `value: "abc"` and numbers cannot be searched by contents. – Sebastian Simon Aug 18 '21 at 17:35
  • Sebastian - It worked only for single value but if my a is somthing like this ‘abc,def’ then it din’t as abc and def are not proper strings – Singla Aug 19 '21 at 14:49

3 Answers3

2

Something along the lines of:

const conditionalArray = [
  { name: "line", condition: ">=", value: 5 },
  { name: "revene", condition: "<", value: 6 },
];

const dataTofilter = [
  { line: 3, revene: 4, sale: 3, fridge: "lg" },
  { line: 6, revene: 3, sale: 2, fridge: "samsung" },
];

const conditions = {
  '<': (x, y) => x < y,
  '<=': (x, y) => x <= y,
  '>': (x, y) => x > y,
  '>=': (x, y) => x >= y,
};

const result = dataTofilter.filter(data => {
  for (const el of conditionalArray) {
    if (!conditions[el.condition](data[el.name], el.value)) {
      return false;
    }
  }
  return true;
});

console.log(result);
MikeM
  • 13,156
  • 2
  • 34
  • 47
0

I'm really not a big fan of it. But I don't see another way as eval() to make the condition work as an actual operator without doing plenty of manual checks. Also the following solution assumes that every item in dataToFilter has a corresponding item in conditionalArray.

const conditionalArray = [
  { name: "line", condition: ">=", value: 5 },
  { name: "revene", condition: "<", value: 6 },
];

const dataTofilter = [
  { line: 3, revene: 4, sale: 3, fridge: "lg" },
  { line: 6, revene: 3, sale: 2, fridge: "samsung" },
];

const result = dataTofilter.filter((item, i) =>
  eval(
    `${item[conditionalArray[i].name]}${conditionalArray[i].condition}${
      conditionalArray[i].value
    }`
  )
);

console.log(result);
Behemoth
  • 5,389
  • 4
  • 16
  • 40
  • I would advise you to avoid `eval`. Use `const operators = { "<"(a, b){ return a < b; }, ">="(a, b){ return a >= b; } };`, etc., then `return operators[conditionalArray[i].condition](conditionalArray[i].name, conditionalArray[i].value);`. Also, the question sounds like _all_ conditions should be applied to _all_ `dataToFilter` objects, not one-by-one, index-by-index. – Sebastian Simon Aug 17 '21 at 18:11
  • Yes, I know it's no a brilliant idea to use `eval`. However it indeed makes it quite a lot simpler for that small problem. If it gets more serious I would, of course, also go with the manual case detection. – Behemoth Aug 17 '21 at 18:16
  • Go with [@MikeM](https://stackoverflow.com/a/68822307/12834972)s solution then. It should be the accepted one for this post in my opinion. I misinterpreted your question a little. – Behemoth Aug 17 '21 at 18:35
0
const newData = dataTofilter.filter((item) => {
   const passedConditions = [];
   conditionalArray.forEach((cond) => {
       switch(cond.condition){
           case ">":
              passedCondition.push(item[cond.name] > cond.value);
              break;
           case ..... //other conditional checks
       }
     }); //end forEach

     return Arrays.asList(passedCondition).contains(false) === false;
});

If you don't want to use eval you can do something like this. We loop through all the data first and use filter to only return values that pass our conditional check.

We then loop trough the conditional array testing each condition on the single item and save the value to passedConditions. You will need to add the rest of the conditions.

Finally we return wether the passedCondtions array did not contain a false value. This would mean we passed all the conditional checks.

Hozeis
  • 1,542
  • 15
  • 36