【问题标题】:How would i filter an array of products with multiple conditions?我将如何过滤具有多种条件的产品数组?
【发布时间】:2020-10-15 12:43:43
【问题描述】:

我正在制作一个电子商务网站,我在显示所有品牌的一侧添加了一个复选框功能,我想过滤产品数组(超过 900 种产品)

         let products = [
            {name: 'computer', category: 'tech'},
            {name: 'soap', category: 'hygiene'},
            {name: 'bbq', category: 'outdoors'}
        ]
        let categoriesToFilterBy = ['tech', 'outdoors'];

        let newProductsArr = products.filter(product => {
            // ??
        })

【问题讨论】:

    标签: javascript arrays reactjs angular filter


    【解决方案1】:

    如果您的categoriesToFilterBy 很大,您可以优化其他解决方案。 Array#filterArray#indexOfArray#includes 都是“隐藏”循环。这将使您的运行时复杂度为 n^m,如果您的 n(产品数量)可以是 900 并且您的 m(过滤器数量)也可能很大,这将是不好的。而是从categoriesToFilterBy 创建一个Set 以获得n 的线性运行时复杂度,因为Set#has 检查是在恒定时间内完成的,无论您的集合有多少元素。

    let categoriesToFilterBy = ['tech', 'outdoors'];
    let filterSet = new Set(categoriesToFilterBy);
    let filteredProducts = products.filter(product => filterSet.has(product.category))
    

    或者如果你必须支持ES5

    let categoriesToFilterBy = ['tech', 'outdoors'];
    let filterSet = {};
    categoriesToFilterBy.forEach(filter => filterSet[filter] = true);
    let filteredProducts = products.filter(product => filterSet[product.category])
    

    或者如果每个产品都有很多类别

    let products = [
       { name: 'computer', categories: ['tech'] },
       { name: 'soap', categories: ['hygiene', 'tech'] }, 
       { name: 'bbq', categories: ['outdoors'] }
    ];
    
    let categoriesToFilterBy = ['tech', 'outdoors'];
    let filterSet = new Set(categoriesToFilterBy);
    let filteredProducts = products.filter(product => 
       product.categories.some(category => filterSet.has(category))
    );
    

    【讨论】:

    • .has() 是否将category 中的所有元素与filterSet 中的元素进行比较?那么时间复杂度不还是n^m吗?
    • 它确实会比较所有元素,但这种比较是在恒定的 O(1) 时间内完成的。它就像在 javascript 对象中查找密钥一样。这就是为什么集合中的值是唯一的。
    【解决方案2】:
            let categoriesToFilterBy = ['tech', 'outdoors'];
    
            let newProductsArr = products.filter(product => {
                for(let i = 0; i < categoriesToFilterBy.length; i++){
                    if(categoriesToFilterBy[i] === product.category) return true;
                }
            })
    

    您只需在过滤器函数中添加一个 for 循环,如果任何条件匹配,则返回 true。

    【讨论】:

    • 最好使用 indexOf 或包含等,而不是使用循环
    • @pc_coder 不幸的是,indexOfincludes 也使用内部循环并具有线性运行时间:(
    • @Caleb Justice 您的 if 语句有误。应该是if(categoriesToFilterBy[i] === product.category)
    猜你喜欢
    • 1970-01-01
    • 2021-07-05
    • 2019-03-02
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2019-11-20
    • 2011-03-21
    • 2010-10-16
    相关资源
    最近更新 更多