具有动态过滤条件的JS Array.filter

时间:2015-07-01 20:04:24

标签: javascript

如何动态声明一组过滤条件而无需指定过滤器数量?

例如,如果我有一组数据,如下所示:

var data = [ 
  { item: { type: 'wood', size: 10 } }, 
  { item: { type: 'wood', size: 8 } },
  { item: { type: 'metal', size: 8 } } 
]

我知道我可以使用JS .filter()获取包含type woodsize 8的所有项目:

function filterItems() {
  return data.filter(function(val) {
    return val['item'].type == 'wood' && 
           val['item'].size == 8;
  }
}

但是,如果我想过滤使用未知数量的过滤条件的商品,并.filter()返回符合这些条件的所有data项,该怎么办?

反映上述代码的

Here is a codepen

4 个答案:

答案 0 :(得分:8)

您可以将一系列条件传递给filterItems()函数。试试这个:

function filterItems(filters) {
  return data.filter(function(val) {
    for(var i = 0; i < filters.length; i++)
      if(val['item'][filters[i][0]] != filters[i][1])
        return false;
    return true;
  }
}
filterItems([['type', 'wood'], ['size', 8], ['someother', 'value']]);

同样的想法可以应用于各种格式,例如使用对象而不是数组来提高可读性。

答案 1 :(得分:1)

我只是对 Amit 对任何数据结构和嵌套属性支持的回答进行了一行重构

from typing import Dict, Any
from pydantic import BaseModel


class Model(BaseModel):
    __root__: Dict[str, Any]

    def __iter__(self):
        return iter(self.__root__)

    def __getattr__(self, item):
        return self.__root__[item]


m = Model.parse_obj({'key1': 'val1', 'key2': 'val2'})
assert m.key1 == "val1"

答案 2 :(得分:0)

function isSingle(filter) {
    return (filter && 'o' in filter && 'm' in filter && 'v' in filter);
}

function isComposite(filter) {
    return (filter && 'lo' in filter);
}

function createBody(filter) {

    if (isComposite(filter)) {
        var bdy = "";
        if (filter.v.length > 1) {
            var o = filter.lo;
            return "(" + createBody(filter.v.shift()) + " " + o + " " + createBody({ lo: filter.lo, v: filter.v }) + ")";
        } else if (filter.v.length == 1) {
            return createBody(filter.v.shift());
        }
        return bdy;
    } else if (isSingle(filter)) {
        var o = filter.o;
        if (typeof filter.v == "string") filter.v = "'" + filter.v + "'"
        return "item." + filter.m + " " + o + "  " + filter.v;
    }
}
var createFunc = function (filter) {

    var body = createBody(filter);
    var f = new Function("item", " return " + body + ";");
    return f;
}

function applyFilter(input, filter) {
    if (filter == undefined) {
        return input;
    }

    var fun = createFunc(filter);
    var output = input.filter(fun);
    return output;
};
//m:member,o:operator,v:value.

var filterQuery1 = { m: "item.type", o: "==", v: "metal" };//simpe query
var filterQuery2 = { m: "item.size", o: ">", v: 8 };
var filterQuery3 = {
    lo: "&&", v: [
        { m: "item.type", o: "==", v: "metal" },
        { m: "item.size", o: "<", v: 9 }]
}; //composite query
var data = [
  { item: { type: 'wood', size: 10 } },
  { item: { type: 'wood', size: 8 } },
  { item: { type: 'metal', size: 8 } }
]
var result = applyFilter(data, filterQuery1);// or filterQuery2,filterQuery3

console.log(result);

https://jsfiddle.net/kd0kL098/

答案 3 :(得分:0)

Amit的回答很好,但我想补充一下。就我而言,我需要返回所有参数,否则返回none / false。这是阿米特(Amit)的编辑代码

function filterItems(filters) {
  return data.filter(function(val) {
    let result = true;
    for(var i = 0; i < filters.length; i++)
      if(val['item'][filters[i][0]] != filters[i][1])
        result = false;
    return result;
  }
}
filterItems([['type', 'wood'], ['size', 8], ['someother', 'value']]);