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

4

需要根据包含多个数组的筛选对象来过滤数组

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

但我无法在过滤器级别应用多个迭代来包含元素。希望了解一种高效的数组过滤方式。


(例如)filterCriteria.region 是否必须包含 vendors[].region 中的所有值,还是只需包含任意一个 - Nick
任何一个都可以工作。 - jinks
1
查看 'some()' :https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Objets_globaux/Array/some - AlainIb
3个回答

4
你可以采用相同的键来处理 filterCriteria,以达到动态效果。
此方法检查筛选值是否为数组,并迭代值并使用 includes 进行检查。
如果不是数组,则直接进行值比较。

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


0

我需要稍微解释一下你的问题。在以下代码中,我们检查每个过滤器是否所有过滤器属性值的元素也在给定的供应商对象属性中(基本上是一个子集操作)。如果你的意思是对于每个过滤器任何元素,你需要使用交集操作。

为了实现这一点,我们可以使用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);


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)

这个回答如何解决问题? - Nick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接