代码之家  ›  专栏  ›  技术社区  ›  cheesydoritosandkale

筛选具有多个条件和部分匹配的对象数组

  •  -1
  • cheesydoritosandkale  · 技术社区  · 7 年前

    我已经发现了很多针对具有多个条件的对象数组的过滤器,但它们似乎是完全匹配的。我需要一种方法来过滤部分匹配。我似乎找到了其中一个。

    let products = [
      { name: "A", color: "Blue", size: 50 },
      { name: "B", color: "Blue", size: 60 },
      { name: "C", color: "Black", size: 70 },
      { name: "D", color: "Green", size: 50 },
    ];
    
    let filters = {
      color: "Blue",
      size: "70"
    };
    
    function multiFilter(array, filters) {
      const filterKeys = Object.keys(filters);
      return array.filter((item) => {
      return filterKeys.every(key => !!~filters[key].indexOf(item[key]));
      });
    
    var filtered = multiFilter(products, filters);
    

    ( https://gist.github.com/jherax/f11d669ba286f21b7a2dcff69621eb72 )

    3 回复  |  直到 7 年前
        1
  •  1
  •   James    7 年前

    要转换现有代码,需要像@Vasan指出的那样切换过滤器。

    products 将进行检查,以查看 filters 产品

        let products = [
          { name: "A", color: "Blue", size: 50 },
          { name: "B", color: "Blue", size: 60 },
          { name: "C", color: "Black", size: 70 },
          { name: "D", color: "Green", size: 50 }
        ];
        
        let filters = {
          color: "Blu",
          size: "50"
        };
    
        function multiFilter(array, filters) {
          const filterKeys = Object.keys(filters);
          return array.filter((item) => {
            // flipped around, and item[key] forced to a string
            return filterKeys.every(key => !!~String(item[key]).indexOf(filters[key]));
          });
        }
    
        var filtered = multiFilter(products, filters);
        console.log(filtered);
        2
  •  1
  •   Prince Hernandez    7 年前

    基本上你要找的是一个 Regular Expression . 你需要改变

    filterKeys.every(key => !!filters[key].indexOf(item[key]))

    !filterKeys.some(key => RegExp(filters[key], 'i').test(item[key].toString()));

    当然要小心使用 item[key].toString() 因为根据具体情况,它可能会给您带来问题,在本例中,我使用它是因为数字(产品的尺寸键)。

    let products = [{
        name: "A",
        color: "Blue",
        size: 50
      },
      {
        name: "B",
        color: "Blue",
        size: 60
      },
      {
        name: "C",
        color: "Black",
        size: 70
      },
      {
        name: "D",
        color: "Green",
        size: 50
      },
      {
        name: "D",
        color: "bluePartial", //you are looking for blue, but blue is a substring of bluepartial, this will be filtered as well
        size: 50
      },
      {
        name: "D",
        color: "violet",
        size: 700 // same as above, 70 is a substring of 700
      },
    ];
    
    // the value of each key is an array with the values to filter
    let filters = {
      color: "Blue",
      size: "70"
    };
    
    function multiFilter(array, filters) {
      const filterKeys = Object.keys(filters);
      return array.filter((item) => {
        return !filterKeys.some(key => RegExp(filters[key], 'i').test(item[key].toString()));
      });
    }
    
    var filtered = multiFilter(products, filters);
    console.log(filtered)
        3
  •  1
  •   Akrion    7 年前

    您可以尝试以下方法:

    let rows = [ { name: "A", color: "Blue", size: "50" }, { name: "B", color: "Blue", size: "60" }, { name: "C", color: "Black", size: "70" }, { name: "D", color: "Green", size: "50" }, ];
    
    const filter = (a, f) => {
      let keys = Object.keys(f)
      if(keys.length == 1) {
        return a.filter(x => x[keys[0]].toLowerCase().includes(f[keys[0]].toLowerCase()))
      } else return a.filter(x => Object.values(f).every(fv => {
        return Object.values(x).some(v => v.toLowerCase().includes(fv.toLowerCase()))
      }))
    }
    
    console.log(filter(rows, {color: "Blu", size: "50"}))
    console.log(filter(rows, {color: "G", size: "5"}))
    console.log(filter(rows, {name: "b"}))
    console.log(filter(rows, {size: "6"}))

    filter 按字段值(否则 b 将匹配两个 name: "B" color: "Blue" 结果不是1,而是3),但如果要对来自 滤波器

    代码使用 String.includes 处理部分匹配和 String.toLowerCase 对价值观进行比较处理。

    推荐文章