React:将多个过滤器应用于数组
React: apply multiple filters to array
我从 React 开始,我有一个名为 arrayToFilter 的对象数组,我想应用多个过滤器,理想情况下,当用户更改过滤器 select 选项时,所有过滤器都应应用于该数组,并且结果返回到 filteredResults 数组中显示,我已经有了每个过滤器函数及其常量,但我不知道如何一个接一个地应用所有过滤器...
这是我的代码:
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 中观察 属性,我想在过滤器输入更改时触发所有过滤器
您可以在数组中将多个过滤器链接在一起。
arrayToFilter
.filter(item => item.category_id.includes(selectedCategoryOptions))
.filter(item => item.discounts.length > 0)
.filter((item) => item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) != -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]);
我可以建议另一种方法,使用 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
})
我从 React 开始,我有一个名为 arrayToFilter 的对象数组,我想应用多个过滤器,理想情况下,当用户更改过滤器 select 选项时,所有过滤器都应应用于该数组,并且结果返回到 filteredResults 数组中显示,我已经有了每个过滤器函数及其常量,但我不知道如何一个接一个地应用所有过滤器...
这是我的代码:
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 中观察 属性,我想在过滤器输入更改时触发所有过滤器
您可以在数组中将多个过滤器链接在一起。
arrayToFilter
.filter(item => item.category_id.includes(selectedCategoryOptions))
.filter(item => item.discounts.length > 0)
.filter((item) => item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) != -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]);
我可以建议另一种方法,使用 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
})