javascript - 如何整理具有许多条件的 JavaScript 过滤函数?

标签 javascript

我正在使用 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/

相关文章:

javascript - 重写 history.pushState 导致 opera 11 出错

javascript - jQuery 杀死 Lightbox

javascript - 如何附加复选框名称?

java - 所描述的 Web 应用程序开发方法有哪些风险?

javascript - 从错误的元素给出的坐标

javascript - 如果在 JavaScript 中未定义,则设置一个变量

javascript 不执行函数

javascript - Bootstrap btn-group-toggle 根据值更改另一个组

javascript - 从带有来自 cypress 的 <br> 标签的元素中获取行分隔文本

javascript - 如何添加下一个和上一个按钮 --- Turn.js