【问题标题】:How to filter object based on many values如何根据多个值过滤对象
【发布时间】:2020-10-27 16:50:19
【问题描述】:

免责声明:我知道这个主题非常不具体。但我不知道如何更好地描述我的问题。请随时在 cmets 中帮助我,我稍后会更新它。


我从 MySQL 数据库中获取一组对象到我的 React 应用程序组件。它有这样的结构:

const fetchedData = [
    {
        "id":         46923,
        "type":       "Change Request",
        "business":   "Systems",
        "owner":      "Max",
        "created_on": "2019-08-16T05:39:00.000Z",
        "many more":  "values",
    },
    {
        "id":         46924,
        "type":       "Change Notice",
        "business":   "Tools",
        "owner":      "Max",
        "created_on": "2019-09-06T11:19:00.000Z",
        "many more":  "values",
    },
]

类型只能有三个值:

  • 更改请求
  • 变更通知
  • 更改任务

业务只能具有三个值:

  • 系统
  • 工具
  • 杂项

我有一个反应组件,每个值都有复选框:

function ControlBoard({ applyFilter }) {
  const classes = useStyles();

  const [state, setState] = useState({
    business: {
      systems: false,
      tools: false,
      misc: false,
    },
    type: {
      changerequest: false,
      changenotice: false,
      changetask: false,
    },
  });

  const handleChange = (event) => {
    const split = event.target.name.split("|");
    const group = split[0];
    const name = split[1];
    let prop = state;
    prop[group][name] = event.target.checked;
    setState({ ...prop });
  };

  const setFilter = () => {
    applyFilter(state);
  };

  useEffect(() => {
    setFilter();
  }, [state]);

  return (
    <div className={classes.root}>
      <div className={classes.title}>Businesses</div>
      <div className={classes.items}>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.business.systems}
                onChange={handleChange}
                name="business|systems"
                color="primary"
              />
            }
            label="Systems"
          />
        </div>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.business.tools}
                onChange={handleChange}
                name="business|tools"
                color="primary"
              />
            }
            label="Tools"
          />
        </div>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.business.misc}
                onChange={handleChange}
                name="business|misc"
                color="primary"
              />
            }
            label="Misc"
          />
        </div>
      </div>

      <div className={classes.title}>Type</div>
      <div className={classes.items}>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.type.changerequest}
                onChange={handleChange}
                name="type|changerequest"
                color="primary"
              />
            }
            label="Change Request"
          />
        </div>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.type.changenotice}
                onChange={handleChange}
                name="type|changenotice"
                color="primary"
              />
            }
            label="Change Notice"
          />
        </div>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.type.changetask}
                onChange={handleChange}
                name="type|changetask"
                color="primary"
              />
            }
            label="Change Task"
          />
        </div>
      </div>
    </div>
  );
}

export default ControlBoard;

因此我有我的状态对象:

{
   business: {
      systems: false,
      tools: false,
      misc: false,
   },
   type: {
      changerequest: false,
      changenotice: false,
      changetask: false,
   },
}

如何根据state 过滤我的fetchedData 数组?布尔值(包括业务和类型的多个真值)的每种组合都是可能的。以后会有比业务和类型更多的价值。

要检查获取的数据值,可以使用例如:

state.type[0].toUpperCase() === fetchedDataRow.type.toUpperCase().replace(" ", "")

【问题讨论】:

    标签: javascript arrays reactjs sorting


    【解决方案1】:

    您可以使用对象键创建这样的匹配函数,这里我们遍历状态和值的每个键,如果其中任何一个为真,我们将检查它。

    你可以看到下面的输出

    const fetchedData = [{
        "id": 46923,
        "type": "Change Request",
        "business": "Systems",
        "owner": "Max",
        "created_on": "2019-08-16T05:39:00.000Z",
        "many more": "values",
      },
      {
        "id": 46924,
        "type": "Change Notice",
        "business": "Tools",
        "owner": "Max",
        "created_on": "2019-09-06T11:19:00.000Z",
        "many more": "values",
      },
    ]
    
    const state = {
      business: {
        systems: true,
        tools: true,
        misc: false,
      },
      type: {
        changerequest: false,
        changenotice: false,
        changetask: false,
      },
    };
    
    
    const isMatch = (criteria, item) => {
      let output = true;
    
      Object.keys(criteria).forEach((element) => {
        const shouldCheck = Object.keys(criteria[element]).some((x) => (criteria[element][x]));
    
        if (shouldCheck) {
          output = output && Object.keys(criteria[element]).some((x) => {
            return criteria[element][x] && x.toUpperCase() === item[element].toUpperCase().replace(" ", "");
          });
        }
      });
      return output;
    };
    
    
    console.log(fetchedData.filter(x => isMatch(state, x)))

    【讨论】:

    • 这是一个很好且有用的答案,但如果多个 businesstype 值为 true,则它不起作用。例如。 {business: {systems: true, tools: true, misc: false}, type: {changerequest: true, changenotice: true, changetask: false}}
    • 越来越近了。现在,当我过滤多个业务时,它忽略了类型的业务价值。这意味着,当我检查工具和系统时,一切正常。当我添加变更请求时,无论业务是什么,它都会添加每个变更请求。
    • 让我检查一下并回复你
    • @T.Karter 你现在可以检查一下吗:)
    • 就是这样!太好了!
    【解决方案2】:

    而不是在对象中创建所有字段。如何创建一个数组,其中仅存在您要应用过滤器的那些值。在这种情况下,您不必维护所有字段状态。

     var filter = {
            business: ['systems','tools'],
            type: ['changerequest']
     };
    

    并根据该过滤条件创建一个过滤器,如下所示:-

    const fetchedData = [{
        "id": 46923,
        "type": "Change Request",
        "business": "Systems",
        "owner": "Max",
        "created_on": "2019-08-16T05:39:00.000Z",
        "many more": "values",
      },
      {
        "id": 46924,
        "type": "Change Notice",
        "business": "Tools",
        "owner": "Max",
        "created_on": "2019-09-06T11:19:00.000Z",
        "many more": "values",
      }
    ];
    
    var filter = {
            business: ['Systems','tools'],
            type: ['Change Request']
     };
    
    var result = fetchedData.filter(item => {
       for (var key in filter) {
          return filter[key].indexOf(item[key]) != -1;
       }
    });
    
    console.log(result);

    【讨论】:

      【解决方案3】:

      .toLowerCase() 和 replace(' ','') 用于形成 fetchedData 以匹配状态键。

      const fetchedData = [{
          "id": 46923,
          "type": "Change Request",
          "business": "Systems",
          "owner": "Max",
          "created_on": "2019-08-16T05:39:00.000Z",
          "many more": "values",
        },
        {
          "id": 46924,
          "type": "Change Notice",
          "business": "Tools",
          "owner": "Max",
          "created_on": "2019-09-06T11:19:00.000Z",
          "many more": "values",
        },
      ]
      
      const state = {
        business: {
          systems: false,
          tools: true,
          misc: false,
        },
        type: {
          changerequest: false,
          changenotice: true,
          changetask: false,
        },
      }
      
      const result = fetchedData.filter((obj) => {
        let businessMatch = false;
        let typeMatch = false;
        for (const [key, value] of Object.entries(state.business)) {
          if (key === obj.business.toLowerCase() && value) {
            businessMatch = true;
            break;
          } else {
            businessMatch = false
          }
        }
      
        for (const [key, value] of Object.entries(state.type)) {
          if (key === obj.type.toLowerCase().replace(' ', '') && value) {
            typeMatch = true;
            break;
          } else {
            typeMatch = false
          }
        }
      
        if (businessMatch && typeMatch) return obj;
      })
      
      console.log(result)

      【讨论】:

      • 此代码不检查任何组合。业务和类型可以有多个真值
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-02
      • 2023-04-03
      • 2015-05-30
      • 2018-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多