【问题标题】:Filter javascript objects array based on a multivalue object基于多值对象过滤javascript对象数组
【发布时间】:2020-07-04 15:49:53
【问题描述】:

需要根据具有多个值组成数组的过滤器对象来过滤数组

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

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

【问题讨论】:

标签: javascript arrays object filter


【解决方案1】:

我不得不稍微解释一下你的问题。因此,在下面的代码中,我们检查每个过滤器是否过滤器属性值的 所有 元素也在给定的供应商对象属性中(基本上是子集操作)。如果您为每个过滤器指定 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);

【讨论】:

    【解决方案2】:

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

    此方法检查过滤器值是否为数组并迭代值并检查包含。

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

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

    【讨论】:

      【解决方案3】:
      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)
      

      【讨论】:

      • 这如何回答这个问题?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-11
      • 1970-01-01
      • 1970-01-01
      • 2020-02-17
      • 2018-08-17
      相关资源
      最近更新 更多