You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据筛选对象的键与值动态过滤对象数组?

动态筛选订单数组问题

原始数据

订单数组

let filteredOrders = []; // 输出数组

let orders = [
    {
        id: 1,
        name: "ORDER 1",
        material: "8756"
    },
    {
        id: 2,
        name: "ORDER 2",
        material: "4548"
    },
    {
        id: 3,
        name: "ORDER 3",
        material: "8756"
    },
    {
        id: 4,
        name: "ORDER 4",
        material: "5678"
    }
]

筛选条件对象

let filters = {
    materials: {
        selected: ""
    },
    ids: {
        selected: ""
    }
}

筛选需求

  • 当筛选条件的selected值不为空字符串且不为"all"时,需用该条件过滤订单数组
  • 支持单个或多个筛选条件同时生效
  • 过滤逻辑必须动态实现,禁止硬编码指定订单对象的键名

预期示例

示例1:单一材质筛选

设置筛选条件:

filters.materials.selected = "8756";

预期输出:

filteredOrders = [
    {
        id: 1,
        name: "ORDER 1",
        material: "8756"
    },
    {
        id: 3,
        name: "ORDER 3",
        material: "8756"
    }
]

示例2:多条件组合筛选

设置筛选条件:

filters.materials.selected = "8756";
filters.ids.selected = 3;

预期输出:

filteredOrders = [
    {
        id: 3,
        name: "ORDER 3",
        material: "8756"
    }
]

问题代码及异常现象

尝试了以下代码实现:

for (var [key, value] of Object.entries(filters)) {
    filteredOrders = orders.filter(function(order) {
        if (filters[key].selected !== "all" && filters[key].selected !== "") {
            if (order[key.slice(0, -1)] == filters[key].selected) {
                console.error("ADD", order, order[key.slice(0, -1)], filters[key].selected); 
                return order;
            }
        }
    });
}

// 为空时返回原数组
if (filteredOrders.length < 1) filteredOrders = orders; 

异常现象:当同时设置materials.selected="8756"和ids.selected=3时,得到的filteredOrders数组包含3条订单,id为2、3、3(出现重复的id=3数据),不符合预期。


问题分析

  1. 过滤数据源错误:每次循环都直接基于原始orders数组过滤,而非上一次的过滤结果,导致最后一次的过滤会覆盖之前的结果,多条件组合逻辑失效
  2. 闭包变量问题:使用var声明循环变量key,导致filter回调中访问的key始终是循环的最后一个值
  3. filter返回值错误:filter回调需要返回布尔值,而代码中返回order对象(对象在布尔判断中为true,但逻辑上未处理不满足条件的情况)

解决方案

实现思路

  1. 先收集所有有效的筛选条件:遍历filters对象,提取selected不为空且不为"all"的条件,同时将筛选键名转换为订单对象对应的属性名(比如materials转为material)
  2. 使用filter遍历订单数组,每个订单需满足所有有效筛选条件
  3. 若没有有效筛选条件,直接返回原始订单数组

代码实现

// 收集有效筛选条件
const validFilters = [];
for (const [filterKey, filterValue] of Object.entries(filters)) {
    const { selected } = filterValue;
    if (selected !== "" && selected !== "all") {
        // 将筛选键名转为订单对象的属性名(去掉末尾的s)
        const orderKey = filterKey.slice(0, -1);
        validFilters.push({ key: orderKey, value: selected });
    }
}

// 执行过滤:若没有有效条件则返回原数组,否则检查每个订单是否满足所有条件
filteredOrders = validFilters.length === 0 
    ? [...orders]
    : orders.filter(order => {
        return validFilters.every(({ key, value }) => {
            // 注意类型匹配,这里用==兼容字符串和数字的情况,若需要严格匹配可改为===
            return order[key] == value;
        });
    });

测试验证

  • 单条件筛选(materials.selected="8756"):返回id=1、3的订单,符合预期
  • 多条件筛选(materials.selected="8756"+ids.selected=3):仅返回id=3的订单,符合预期
  • 无有效条件(所有selected为空或"all"):返回原始订单数组

内容的提问来源于stack exchange,提问作者Anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:53:12