在多个条件下过滤具有多个属性的对象数组

时间:2017-02-07 09:32:25

标签: javascript

我试图在多个条件下过滤具有多个属性的对象数组。所以我正在创建一个param数组,它由包含参数的多个数组组成。例如

var params = [
    ["id", "equals", "11060"],
    ["user_id", "exact", "84"]
];

第一个元素是键,第二个元素是条件,第三个元素是值。 所以第一个过滤条件是 id == '11060',第二个是user_id = '84'

// data to filter
    var originalData = [{
        "id": 11141,
        "user_id": 84,
        "received": "26 Jan 2017",
        "approvalstatus": "Approved"
    }, {
        "id": 11080,
        "user_id": 84,
        "received": "25 Jan 2017",
        "approvalstatus": "Approved"
    }, {
        "id": 11079,
        "user_id": 84,
        "received": "25 Jan 2017",
        "approvalstatus": "Approved"
    }, {
        "id": 11078,
        "user_id": 84,
        "received": "25 Jan 2017",
        "approvalstatus": "Approved"
    }, {
        "id": 11060,
        "user_id": 84,
        "received": "24 Jan 2017",
        "approvalstatus": "Approved"
    }];

以下是我的过滤功能。

   filteredData = originalData.filter(function(item) {
        params.forEach(function(value, index) {
            var cond = value[1];
            var cKey = value[0];
            var cValue = value[2];
            var flag = false;
            if (cond == 'equals') {
                if (item[cKey] == Number(cValue)) {
                    flag = true;
                }
            } else if (cond == 'exact'){
                if (item[cKey].toString() == cValue) {
                    flag = true;
                }
            }
            return flag;
        });
        return false;
    });

但它不起作用。我做错了什么? TIA。

jsfiddle

4 个答案:

答案 0 :(得分:3)

你做一个forEach(),返回值不会作为过滤函数的返回值传输。 此外,您还没有确定该值是否必须成功通过所有测试或仅通过一个。我认为它必须成功通过所有测试。 如果它只是其中之一,则代码略有不同。

{{1}}

答案 1 :(得分:1)

问题:

您无法从forEach返回。 forEach会将数组返回filter,数组 truthy 。因此,结果数据将包含所有元素。

解决方案:

可以使用

for代替forEach。要检查是否满足数组中的所有条件,请检查flag是否设置为false并从那里返回以从结果数组中排除该元素。



var originalData = [{
    "id": 11141,
    "user_id": 84,
    "received": "26 Jan 2017",
    "approvalstatus": "Approved"
}, {
    "id": 11080,
    "user_id": 84,
    "received": "25 Jan 2017",
    "approvalstatus": "Approved"
}, {
    "id": 11079,
    "user_id": 84,
    "received": "25 Jan 2017",
    "approvalstatus": "Approved"
}, {
    "id": 11078,
    "user_id": 84,
    "received": "25 Jan 2017",
    "approvalstatus": "Approved"
}, {
    "id": 11060,
    "user_id": 84,
    "received": "24 Jan 2017",
    "approvalstatus": "Approved"
}];


var params = [
    ["id", "equals", "11060"],
    ["user_id", "exact", "84"]
];


filteredData = originalData.filter(function(item) {
    var flag = false;

    for (var i = 0; i < params.length; i++) {
        var value = params[i];
        var condition = value[1];

        if (condition === 'equals') {
            flag = item[value[0]] === Number(value[2]);
        } else if (condition === 'exact') {
            flag = item[value[0]].toString() === value[2];
        }

        // If flag is false, return from here
        // No need to check other conditions
        if (flag === false) {
            break;
        }
    }
    return flag;
});

console.log(filteredData);
&#13;
&#13;
&#13;

更好(?)替代

我建议使用对象而不是数组数组来存储过滤条件。

&#13;
&#13;
var originalData = [{
    "id": 11141,
    "user_id": 84,
    "received": "26 Jan 2017",
    "approvalstatus": "Approved"
}, {
    "id": 11080,
    "user_id": 84,
    "received": "25 Jan 2017",
    "approvalstatus": "Approved"
}, {
    "id": 11079,
    "user_id": 84,
    "received": "25 Jan 2017",
    "approvalstatus": "Approved"
}, {
    "id": 11078,
    "user_id": 84,
    "received": "25 Jan 2017",
    "approvalstatus": "Approved"
}, {
    "id": 11060,
    "user_id": 84,
    "received": "24 Jan 2017",
    "approvalstatus": "Approved"
}];


// Filter criteria
var params = {
    id: 11060,
    user_id: 84
};

// Get keys from params
var keys = Object.keys(params);

filteredData = originalData.filter(function(item) {
    var flag = false;
    for (var i = 0; i < keys.length; i++) {
        var key = keys[i];

        // Check if value from filter criterial and
        // current element are equal
        flag = item[key] === params[key];
        if (flag === false) {
            break;
        }
    }
    return flag;
});

console.log(filteredData);
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您可以使用Array#every并检查每个条件。

var params = [["id", "equals", "11060"], ["user_id", "exact", "84"]],
    originalData = [{ id: 11141, user_id: 84, received: "26 Jan 2017", approvalstatus: "Approved" }, { id: 11080, user_id: 84, received: "25 Jan 2017", approvalstatus: "Approved" }, { id: 11079, user_id: 84, received: "25 Jan 2017", approvalstatus: "Approved" }, { id: 11078, user_id: 84, received: "25 Jan 2017", approvalstatus: "Approved" }, { id: 11060, user_id: 84, received: "24 Jan 2017", approvalstatus: "Approved" }],
    filteredData = originalData.filter(function (item) {
        return params.every(function (value) {
            var cond = value[1],
                cKey = value[0],
                cValue = value[2];
            if (cond == 'equals') {
                return item[cKey] == Number(cValue);
            } else if (cond == 'exact') {
                return item[cKey].toString() == cValue;
            }
            return false;
        });
    });

console.log(filteredData);
.as-console-wrapper { max-height: 100% !important; top: 0; }

简短版本,将所有条件转换为函数并使用item调用它。

var params = [["id", "equals", "11060"], ["user_id", "exact", "84"]],        
    conditions = params.map(function (a) {
        switch (a[1]) {
            case 'equals': return function (o) { return o[a[0]] == Number(a[2]); };
            case 'exact': return function (o) { return o[a[0]].toString() == a[2]; };
        }
    }),
    originalData = [{ id: 11141, user_id: 84, received: "26 Jan 2017", approvalstatus: "Approved" }, { id: 11080, user_id: 84, received: "25 Jan 2017", approvalstatus: "Approved" }, { id: 11079, user_id: 84, received: "25 Jan 2017", approvalstatus: "Approved" }, { id: 11078, user_id: 84, received: "25 Jan 2017", approvalstatus: "Approved" }, { id: 11060, user_id: 84, received: "24 Jan 2017", approvalstatus: "Approved" }],
    filteredData = originalData.filter(function (item) {
        return conditions.every(function (condition) {
            return condition(item);
        });
    });

console.log(filteredData);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 3 :(得分:0)

var filteredData = originalData.filter(function(data){ 
  var found = false;
  params.map(function(param){ 
    switch(param[1]){ 
        case "equals":
          if(data[param[0]] == param[2]){ found = true; }
        break;
        case "exact":
          if(data[param[0]] == param[2]){ found = true; }
        break;
    }
  })
  return found;
})

console.log(filteredData);