4

Need to filter array based on a filter object having multiple values consisting arrays

    var vendors = [
      {
        vendor_name: "John",
        region: ["APAC", "UKDE"],
        scanned_status: "Yes",
        channel: ["FILE", "API"],
        pii_attributes: ["A", "B"]
      },
      {
        vendor_name: "Onir",
        region: ["APAC", "LATAM"],
        scanned_status: "No",
        channel: ["FILE"],
        pii_attributes: ["A", "C"]
      },
      {
        vendor_name: "Suresh",
        region: ["UKDE", "NA"],
        scanned_status: "Yes",
        channel: ["API"],
        pii_attributes: ["C", "B"]
      }
    ];

    var filterCriteria = {
      region: ["APAC", "LATAM"], // 'APAC', 'LATAM', 'NA', 'UKDE'
      channel: ["API"], // 'API', 'FILE'
      attributes: ["A", "B"],
      scan_status: "Yes" // 'Yes', 'No', 'All'
    };
    let filtered_vendors = [];
    var result = vendors.filter((el, index, arr) => {
      if (
        filterCriteria["region"].includes(el["region"]) &&
        filterCriteria["channel"].includes(el["channel"]) &&
        filterCriteria["attributes"].includes(el["pii_attributes"])
      ) {
        filtered_vendors.push(el);
        return true;
      }
      return false;
    });

    console.log(result);
    console.log(filtered_vendors);

But I am not able to apply multiple iteration at the filter level for including the elements. WOuld like to know efficient way to filter the array.

3
  • Does (for example) filterCriteria.region have to include all values from vendors[].region or any of them? Commented Mar 24, 2020 at 7:03
  • any of them will work. Commented Mar 24, 2020 at 7:04
  • 1
    look at 'some()' developer.mozilla.org/fr/docs/Web/JavaScript/Reference/… Commented Mar 24, 2020 at 7:08

3 Answers 3

4

You could take a dynamic approach by using same keys for filterCriteria as well.

This approach checks if the filter value is an array and iterates the values and checks with includes.

If no array then it compares the value directly.

var vendors = [{ vendor_name: "John", region: ["APAC", "UKDE"], scanned_status: "Yes", channel: ["FILE", "API"], pii_attributes: ["A", "B"] }, { vendor_name: "Onir", region: ["APAC", "LATAM"], scanned_status: "No", channel: ["FILE"], pii_attributes: ["A", "C"] }, { vendor_name: "Suresh", region: ["UKDE", "NA"],
scanned_status: "Yes", channel: ["API"], pii_attributes: ["C", "B"] }],
    filterCriteria = { region: ["APAC", "LATAM"], channel: ["API"], pii_attributes: ["A", "B"], scanned_status: "Yes" },
    filters = Object.entries(filterCriteria),
    result = vendors.filter(o => filters.every(([k, value]) => Array.isArray(value)
        ? value.some(v => o[k].includes(v)) // change to every if all have to match
        : o[k] === value
    ));

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

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

Comments

0
var data = [{
    "id": 1,
    "term_id": 5,
    "type": "car"
  },
  {
    "id": 2,
    "term_id": 3,
    "type": "bike"
  },
  {
    "id": 3,
    "term_id": 6,
    "type": "car"
  }
];

var result = data.filter(function(v, i) {
  return ((v["term_id"] == 5 || v["term_id"] == 6) && v.type == "car");
})

console.log(result)

1 Comment

How does this answer the question?
0

I had to interpret your question a little. So, in the following code, we check if for every filter if all elements of the filter property value are also in the given vendor object property (basically a subset operation). In case you meant any element for every filter you need to use an intersection operation.

To implement this, we can use reduce for the iteration and sum up individual checks with && (function isSupersetOf). To apply this for every filter property, we can apply the same technique on the entries set (function isMatch).

Note that I also had to adjust the property names for this to work.

Code:

var vendors = [
      {
        vendor_name: "John",
        region: ["APAC", "UKDE"],
        scanned_status: "Yes",
        channel: ["FILE", "API"],
        pii_attributes: ["A", "B"]
      },
      {
        vendor_name: "Onir",
        region: ["APAC", "LATAM"],
        scanned_status: "No",
        channel: ["FILE"],
        pii_attributes: ["A", "C"]
      },
      {
        vendor_name: "Suresh",
        region: ["UKDE", "NA"],
        scanned_status: "Yes",
        channel: ["API"],
        pii_attributes: ["C", "B"]
      },
      // Add a match for illustration
      {
        vendor_name: "Denep",
        region: ["APAC", "LATAM", "NA"],
        scanned_status: ["Yes"],
        channel: ["API"],
        pii_attributes: ["A", "B", "C"]
      }
    ];

    const filterCriteria = {
      region: ["APAC", "LATAM"], // 'APAC', 'LATAM', 'NA', 'UKDE'
      channel: ["API"], // 'API', 'FILE'
      pii_attributes: ["A", "B"],
      scanned_status: ["Yes"] // 'Yes', 'No', 'All'
    };
    const isSupersetOf = (subset, superset) => 
      subset.reduce((result, next) => result && superset.includes(next), true);
    const isMatch = (filter, element) => 
      Object.entries(filter)
        .reduce((result, [property, values]) => result && isSupersetOf(values, element[property] || []), true)
    
    const filteredVendors = vendors.filter((el, index, arr) => 
      isMatch(filterCriteria, el))

    console.log(filteredVendors);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.