使用多个过滤器数组过滤一个数组

时间:2019-05-25 06:32:44

标签: javascript arrays filtering

我正在尝试根据多个过滤器数组来过滤项目数组。每个项目都有一个过滤器选择,我只需要显示与所有选定过滤器匹配的过滤器即可。

const selectedFilters = {
    color: ["Red", "Blue"],
    type: ["Shirt"],
    size: ["M"]
};

const items = [
    {
        name: "Item 1",
        filters: {
            color: ["Red", "Blue", "Black"],
            type: ["Shirt"],
            size: ["M"]
        }
    },
    {
        name: "Item 2",
        filters: {
            color: ["Red"],
            type: ["Pants"],
            size: ["M"]
        }
    }
];

这就是我一直试图解决的方式。对所有项目进行过滤-对于每个不为空的过滤器类别,请遍历所有过滤器词,并检查该项目是否与所有词均匹配。

const filterItems = (items, selectedFilters) => {
    const filterKeys = Object.keys(selectedFilters);

    return items.filter(item => {
        return filterKeys.every(key => {

            // Ignore empty filters
            if (!selectedFilters[key].length) {
                return true;
            }

            return selectedFilters[key].every(filterWord => {
                item.filters[key].includes(filterWord);
            });
        });
    });
};

filterItems(items, selectedFilters);

返回一个空数组,应返回一个带有“ Item 1”对象的数组。

5 个答案:

答案 0 :(得分:0)

您可以创建selectedFilters值数组和filters属性值数组。然后在every上使用selectedFilters,检查其中的所有值是否都存在于filters中。

const selectedFilters = {
    color: ["Red", "Blue"],
    type: ["Shirt"],
    size: ["M"]
};

const items = [
    {
        name: "Item 1",
        filters: {
            color: ["Red", "Blue", "Black"],
            type: ["Shirt"],
            size: ["M"]
        }
    },
    {
        name: "Item 2",
        filters: {
            color: ["Red"],
            type: ["Pants"],
            size: ["M"]
        }
    }
];

const filterArr = Object.values(selectedFilters).flat();

const output = items.filter(({filters}) => {
    const objFilters = Object.values(filters).flat();
    return filterArr.every(val => objFilters.includes(val));
})
console.log(output);

答案 1 :(得分:0)

您可以使用some检查数组中是否包含至少一个元素,并且该函数期望布尔返回值。

  

some()方法测试数组中是否至少有一个元素   通过提供的功能实现的测试。它返回一个   布尔值。

const selectedFilters = {"color":["Red","Blue"],"type":["Shirt"],"size":["M"]}
const items = [{"name":"Item 1","filters":{"color":["Red","Blue","Black"],"type":["Shirt"],"size":["M"]}},{"name":"Item 2","filters":{"color":["Red"],"type":["Pants"],"size":["M"]}}]

const filterItems = (items, selectedFilters) => {
  const filterKeys = Object.keys(selectedFilters);
  return items.filter(item => {
    return filterKeys.every(key => {
      return selectedFilters[key].some(filterWord => {   //Use some
        return item.filters[key].includes(filterWord);   //Return the a bool
      });
    })
  });
};

var result = filterItems(items, selectedFilters);
console.log(result);

更短版本:

const selectedFilters = {"color":["Red","Blue"],"type":["Shirt"],"size":["M"]};

const items = [{"name":"Item 1","filters":{"color":["Red","Blue","Black"],"type":["Shirt"],"size":["M"]}},{"name":"Item 2","filters":{"color":["Red"],"type":["Pants"],"size":["M"]}}];

const filterItems = (items, selectedFilters) => {
  const fkeys = Object.keys(selectedFilters);
  return items.filter(i => fkeys.every(k => selectedFilters[k].some(o => i.filters[k].includes(o))));
};

const result = filterItems(items, selectedFilters);
console.log(result);

答案 2 :(得分:0)

您可以为此使用Array.filter()函数。这是解决这个问题的非常简单有效的方法。

Array.prototype.diff = function(arr2) {
    var ret = [];
    for(var i in this) {   
        if(arr2.indexOf(this[i]) > -1){
            ret.push(this[i]);
        }
    }
    return ret;
};

var filteredArr = items.filter(function (el) {
  return el.filters.color.diff(selectedFilters.color).length > 0 &&
         el.filters.type.diff(selectedFilters.type).length > 0 &&
         el.filters.size.diff(selectedFilters.size).length > 0
});

这是工作示例。

https://playcode.io/325371?tabs=console&script.js&output

注意: ,您可以根据自己的要求更改AND / OR条件。

答案 3 :(得分:0)

有很多方法可以解决此问题。例如,您的解决方案是正确的,但是我们需要像这样在每个回调中移除卷曲的{}

filterWord => item.filters[key].includes(filterWord)

另一种选择是使用selectedFilters方法将filterValues转换为flat()数组。此方法创建一个新数组,其中所有子数组元素都以递归方式连接到该数组中。现在,我们提取每个filters的{​​{1}}并再次使用items方法将其转换为itemFilters数组。然后,我们尝试将它们与结合了flat()filterValues方法的every()进行匹配。两者都将测试数组中的所有元素是否包括每个includes()的元素。

第三个选项与您的解决方案非常相似。在这种情况下,我们将filter键提取到selectedFilters数组中。然后,对于每个types,我们将type方法与some()方法结合使用以测试includes()中是否包含数组中的至少一个元素。

这里有实现:

items.filters[type]

答案 4 :(得分:0)

500,9736,264
1000,9472,528
1500,9197,803
2000,8913,1087
2500,8611,1389
3000,8292,1708
3500,7968,2032
4000,7643,2357
4500,7312,2688
5000,6960,3040
5500,6613,3387
6000,6257,3743
6500,5913,4087
7000,5570,4430
7500,5212,4788