【问题标题】:React: apply multiple filters to array反应:将多个过滤器应用于数组
【发布时间】:2020-09-24 14:44:44
【问题描述】:

我从 react 开始,我有一个名为 arrayToFilter 的对象数组,我想应用多个过滤器,理想情况下,当用户更改过滤器选择选项时,所有过滤器都应应用于数组,并将结果返回到过滤结果要显示的数组,我已经有了每个过滤器函数及其常量,但我不知道如何一个接一个地应用所有过滤器...

这是我的代码:

    const [ arrayToFilter, setArrayToFilter ] = useState([ /*array of objects to apply filters to*/ ]);
    const [ filteredResults, setFilteredResults] = useState([ /*array of filtered objects*/ ]);
    const [ categoryOptions, setCategoryOptions ] = useState([ 1,2,3 ]);
    const [ selectedCategoryOptions, setSelectedCategoryOptions ] = useState([ ]);
    const [ searchName, setSearchName ] = useState('');
    const [ hideVenuesWithoutDiscounts, setHideVenuesWithoutDiscounts ] = useState(true);

    const filterHideVenuesWithoutDiscounts = () => 
    {
        if(hideVenuesWithoutDiscounts)
        {
            return arrayToFilter.filter(item => item.discounts.length > 0);
        }
        else
        {
            return arrayToFilter;
        }   
    };

    const filterSelectedCategoryOptions = () => 
    {
        return arrayToFilter.filter(item => item.category_id.includes(selectedCategoryOptions));
    };

    const filtersearchName = () => 
    {
        return arrayToFilter.filter(item =>  item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) != -1);
    };

    useEffect(() => 
    {
        //Filter options updated so apply all filters here
    },
    [searchName, hideVenuesWithoutDiscounts, selectedCategoryOptions]);

注意 useEffect,afaik 这就像 vue 中的 watch 属性,我想在过滤器输入更改时触发所有过滤器

【问题讨论】:

    标签: javascript reactjs native


    【解决方案1】:

    很简单,您可以将过滤后的数组作为参数传递给过滤函数,以便它们对过滤后的数组进行过滤。

    例如:

    const filterHideVenuesWithoutDiscounts = (array) => {
        if (hideVenuesWithoutDiscounts) {
            return array.filter((item) => item.discounts.length > 0);
        } else {
            return array;
        }
    };
    
    const filterSelectedCategoryOptions = (array) => {
        return array.filter((item) => item.category_id.includes(selectedCategoryOptions));
    };
    
    const filtersearchName = (array) => {
        return array.filter((item) => item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) != -1);
    };
    
    useEffect(() => {
        //Filter options updated so apply all filters here
        let result = arrayToFilter;
        result = filterHideVenuesWithoutDiscounts(result);
        result = filterSelectedCategoryOptions(result);
        result = filtersearchName(result);
        setArrayToFilter(result);
    }, [searchName, hideVenuesWithoutDiscounts, selectedCategoryOptions]);
    

    【讨论】:

    • 即使对于像我这样对 JavaScript 和 React 非常幼稚的人来说,这也是最简单且真正可以理解的答案。谢谢!
    【解决方案2】:

    您可以在数组中将多个过滤器链接在一起。

    arrayToFilter
    .filter(item => item.category_id.includes(selectedCategoryOptions))
    .filter(item => item.discounts.length > 0)
    .filter((item) => item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) != -1)
    

    【讨论】:

    • 您的意思是在第二行包含分号吗?
    • 这是一个错字。我的错。
    【解决方案3】:

    我可以建议另一种方法,使用Array.reduce,因为链接Array.filters 每次都会遍历整个数组,如果数组很大,这可能会耗费资源。

    例子:

    const filterMethods = [
      (item => item.category_id.includes(selectedCategoryOptions)),
      (item => item.discounts.length > 0),
      ((item) => item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) != -1)
    ]
    
    const filteredArray = arrayToFilter.reduce((accumulator, currentItem) => {
      for (let i = 0; i < filterMethods.length; i++) {
        if (!filterMethods[i](currentItem)) {
          return accumulator
        }
      }
      return [...accumulator, currentItem]
    }, [])
    

    编辑: 睡了一会后,我注意到您实际上可以像 reduce 一样使用Array.filter,而无需多次遍历数组。

    const filterMethods = [
      (item => item.category_id.includes(selectedCategoryOptions)),
      (item => item.discounts.length > 0),
      ((item) => item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) != -1)
    ]
    
    const filteredArray = arrayToFilter.filter((item) => {
      for (let i = 0; i < filterMethods.length; i++) {
        if (!filterMethods[i](item)) {
          return false
        }
      }
      return true
    })
    

    【讨论】:

    • 我注意到您实际上可能会以类似的方式使用Array.filter,看看编辑,我认为这也适用于您的情况。
    猜你喜欢
    • 2018-05-29
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 2017-10-27
    • 1970-01-01
    • 2014-10-21
    相关资源
    最近更新 更多