我正在使用 React,但我认为这只是一个普通的 JavaScript 问题。在我的数据模型中,我有一个对象数组。这是一个缩短的版本:
this.props.exercises = [
{
name: 'Push up',
equipment: 'none',
group: 'push'
},
{
name: 'Bench press',
equipment: 'Barbell',
group: 'push'
},
{
name: 'Pull-Up Bar',
equipment: 'Pull-Up Bar',
group: 'pull'
},
{
name: 'Dumbbell / Kettlebell Squat',
equipment: ['Dumbbell', 'Kettlebell'],
group: 'legs'
}
]
我需要对此数组进行一些相当复杂的过滤。如果项目的名称与 selectedExercise 字符串匹配,则始终需要返回它。如果这个条件不匹配,那么我需要以下条件:
如果用户选择了一个组,则只应返回该组中的练习。
如果用户输入了搜索文本,那么结果也应该按此过滤。
用户指定他们拥有什么设备,然后结果也应该按此过滤。练习可以不需要任何设备、一件设备,或者有一系列可能的设备选项。
我下面的代码可以工作,但我认为它非常脆弱,如果出现问题,调试将是一场噩梦。什么是更好的方法?函数式编程可以解决这个问题吗?
renderExercises() {
const {selectedType} = this.state;
const allExercises = this.props.exercises;
// If there is search text then create a var for it
let searchText = false;
if (this.searchText && this.searchText.value.length > 0) {
searchText = this.searchText.value.toLowerCase();
}
return (
allExercises
// Set the active exercise to have an active property
.map((item) => {
if (this.props.chosenExercise === item.name) {
item.active = true;
} else {
item.active = false;
}
return item;
})
.filter((item) => {
// If the exercise is active then return true
if (item.active === true) {
return true
}
// Filter by the exercise group if one is selected
if (item.group !== selectedType && selectedType !== 'all') {
return false;
}
// If there is search text then filter out non matches
if (searchText && !item.name.toLowerCase().includes(searchText)) {
return false;
}
// EQUIPMENT CONDITIONS
// If the exercise doesn't need any equipment then return true
if (item.equipment === 'none') {
return true;
}
// If the user has all equipment then return true
if (this.props.equipmentSelectionState === 'all') {
return true;
}
// If the item only has 1 piece of equipment then the type will be a string not an array
if (typeof item.equipment == 'string' || item.equipment instanceof String) {
// If the selected equipment array contains the items's required equipment then return true
if (this.props.equipmentSelection.includes(item.equipment)) {
return true;
} else {
return false;
}
} else {
let test = false;
item.equipment.forEach((itemEquipment => {
if (this.props.equipmentSelection.includes(itemEquipment)) {
test = true;
}
}));
if (test === true) {
return true;
}
}
return false;
})
// Sort by name
.sort((a, b) => {
if (a.name < b.name)
return -1;
if (a.name > b.name)
return 1;
return 0;
})
.map((item) => {
return (
<ChooseAnExercises
key={item.name}
name={item.name}
active={item.active}
setNumber={this.props.number}
updateValue={this.props.updateValue}
/>
)
})
)
}
最佳答案
您可以仅使用 true
条件来缩小过滤器部分,并通过首先采用一般条件来对它们进行排序,然后进行更昂贵的操作,例如迭代数组。
.filter(item =>
item.active ||
item.equipment === 'none' ||
this.props.equipmentSelectionState === 'all' ||
selectedType === 'all' ||
item.group === selectedType ||
searchText && item.name.toLowerCase().includes(searchText) ||
(Array.isArray(item.equipment)
? item.equipment
: [item.equipment]
).some(itemEquipment => this.props.equipmentSelection.includes(itemEquipment))
)
所有条件都通过逻辑“或”链接起来。如有必要,会将字符串转换为数组,以便使用相同的检查进行迭代。
关于javascript - 如何整理具有许多条件的 JavaScript 过滤函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47219166/