简体   繁体   English

如何根据多个值过滤对象

[英]How to filter object based on many values

Disclaimer : I know the topic is very unspecific.免责声明:我知道这个话题非常不具体。 But I don't know how to describe my issue better.但我不知道如何更好地描述我的问题。 Feel free to help me in the comments and I'll update it later.请随时在评论中帮助我,我稍后会更新。


I fetch an array of objects coming from a MySQL database to my React App Component.我从 MySQL 数据库中获取一组对象到我的 React App 组件。 It has this structure:它有这样的结构:

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",
    },
]

The type can have three values only:类型只能有三个值:

  • Change Request改变请求
  • Change Notice变更通知
  • Change Task更改任务

The business can have three values only:业务只能具有三个值:

  • Systems系统
  • Tools工具
  • Misc杂项

I have a react component that has checkboxes for each value:我有一个反应组件,每个值都有复选框:

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;

Thus I have my state object:因此我有我的状态对象:

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

How can I filter my fetchedData array against my state ?如何根据我的state过滤我的fetchedData数组? Each combination of boolean values (including multiple true values of business and type) is possible.布尔值的每种组合(包括业务和类型的多个真值)都是可能的。 Later there will be more values than business and type.以后会有比业务和类型更多的值。

To check against the fetched data values it could be possible to use eg:要检查获取的数据值,可以使用例如:

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

You can create a match function like this using the object keys, here we go through each key of the state and the values and if any of it has true we check it.您可以使用对象键创建这样的匹配函数,在这里我们遍历状态的每个键和值,如果其中任何一个为真,我们将检查它。

You can see the output below你可以看到下面的输出

 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)))

.toLowerCase() and replace(' ','') are used to form the fetchedData to match to state keys. .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)

Rather than creating all the field in the object.而不是创建对象中的所有字段。 How about creating an array in which only those values present on which you wants to apply the filter.如何创建一个数组,其中只存在您想要应用过滤器的那些值。 In this case you don't have to maintain all the field state.在这种情况下,您不必维护所有字段状态。

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

And create a filter base on that filter criteria like below:-并根据该过滤条件创建一个过滤器,如下所示:-

 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM