根据多值对象过滤JavaScript对象数组

时间:2020-03-24 06:51:25

标签: javascript arrays object filter

需要基于具有多个包含数组的值的过滤器对象过滤阵列

    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);

但是我无法在过滤器级别应用多次迭代以包含元素。想知道过滤数组的有效方法。

3 个答案:

答案 0 :(得分:4)

您也可以通过对filterCriteria使用相同的键来采用动态方法。

这种方法检查过滤器值是否为数组,并迭代这些值并使用include进行检查。

如果没有数组,则直接比较该值。

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; }

答案 1 :(得分: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)

答案 2 :(得分:0)

我不得不解释一下你的问题。因此,在下面的代码中,我们检查是否每个过滤器的过滤器属性值的 all 元素也都位于给定的供应商对象属性中(基本上是子集操作)。如果您需要对每个过滤器使用 any 元素,则需要使用交集操作。

要实现此目的,我们可以使用reduce进行迭代,并使用&&(函数isSupersetOf)总结单个检查。要将其应用于每个过滤器属性,我们可以对条目集(函数isMatch)应用相同的技术。

请注意,我还必须调整属性名称才能使其正常工作。

代码:

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);