简体   繁体   English

遍历多个对象的属性

[英]iterate through properties of multiple objects

I am working on a filter engine for my app.我正在为我的应用程序开发过滤引擎。 Right now, I am having issues with the iteration between an object data which I need to check against the array of filters the user applies.现在,我遇到了对象数据之间的迭代问题,我需要根据用户应用的过滤器数组进行检查。 The final goal is to return the object(s) that match one or multiple filter choices.最终目标是返回匹配一个或多个过滤器选项的对象。

Here is my code:这是我的代码:

const Results = () => {
const [dataStored, setDataStored] = useState([])
const filterArray = useSelector(state => state.filterArray);
const doctors = useSelector(state => state.doctors);

// let doctorsResult = doctors.map(doctor => doctor.indexOf(filterArray) !== -1 )

// let doctorsResult = doctors.map(doctor => {for(let key of Object.keys(doctor)){
//     if (key === 'price' || key === 'gender' || key === 'language'){
//     // setDataStored([...dataStored, doctor[key]])
//     console.log("dataStored",doctor[key])}
//     //  return (dataStored.indexOf(filterArray) !== -1 )

// }})

let doctorsResult = doctors.map(doctor => {
    Object.keys(doctor).forEach((key) => {
        if (key === 'price' || key === 'gender' || key === 'language') {
            setDataStored([...dataStored, doctor[key]])
            console.log("dataStored", dataStored)
        }
        return (dataStored.indexOf(filterArray) !== -1)
    })
})

Each object has multiple properties, but I only need to check the 'price, gender, and language' values.每个对象都有多个属性,但我只需要检查“价格、性别和语言”值。 Properties are not equal, some are just a string, others are an array.属性不相等,有些只是一个字符串,有些则是一个数组。 So far, I have been able to do the iteration through the properties using for..in and forEach loops.到目前为止,我已经能够使用 for..in 和 forEach 循环通过属性进行迭代。 My issue is, I am not able to compare and return any data because it is not an array, therefore, indexOf() gives me an error.我的问题是,我无法比较和返回任何数据,因为它不是数组,因此 indexOf() 给了我一个错误。 When I try setDataStored([...dataStored, doctor[key]]) , the State goes into infinite loop.当我尝试setDataStored([...dataStored, doctor[key]]) ,状态进入无限循环。

I am fairly new to all this.我对这一切都很陌生。 If someone has a better way to achieve this, I will really appreciate it.如果有人有更好的方法来实现这一目标,我将不胜感激。

Edit:编辑:

Here is the shape of filterArray It's a dynamic filter, starts empty and then gets populated这是 filterArray 的形状这是一个动态过滤器,从空开始然后填充

![在此处输入图片说明

So you want to get the state from two selectors and do some work, then return the result?所以你想从两个选择器中获取状态并做一些工作,然后返回结果? This is the perfect type of problem for reselect .这是reselect的完美问题类型。 Reselect is a helper that allows you to memoize expensive calculations regarding state selectors. Reselect 是一个帮助器,它允许您记住有关状态选择器的昂贵计算。

https://github.com/reduxjs/reselect https://github.com/reduxjs/reselect

Heres what that could look like for you.这就是你的样子。

$ yarn add reselect

import React from 'react';
import { useSelector } from 'react-redux';
import { createSelector } from 'reselect';

const filterArraySelector = (state) => state.filterArray;
const doctorsSelector = (state) => state.doctors;

const filteredDoctorsSelector = createSelector(doctorsSelector, filterArraySelector, (filterArray, doctors) => {
  return doctors.filter((doctor) => {
    return filterArray.all((key) => {
      // Do some comparison here, return true if you want to include the doctor in the results
      return doctor[key] !== undefined;
    });
  });
});

const Results = () => {
  const filteredDoctors = useSelector(filteredDoctorsSelector);

  return filteredDoctors.map((doctor) => <span>{doctor}</span>);
};

Alternative Option替代选项

Instead of using createSelector to memoize the filtering, you can simply filter the doctors every time you render.您可以在每次渲染时简单地过滤医生,而不是使用createSelector来记忆过滤。 Like this:像这样:

const Results = () => {
  const filterArray = useSelector((state) => state.filterArray);
  const doctors = useSelector((state) => state.doctors);

  const filteredDoctors = useMemo(
    () =>
      doctors.filter((doctor) => {
        return filterArray.all((key) => {
          // Do some comparison here, return true if you want to return the doctor
          return doctor[key] !== undefined;
        });
      }),
    [doctors, filterArray]
  );

  return filteredDoctors.map((doctor) => <span>{doctor}</span>);
};

Update:更新:

Given a filterArray of values like this:给定一个 filterArray 这样的值:

const filterArray = ['Female', 'English'];

We can update the filter function to test the Objects values against the filterArray values.我们可以更新 filter 函数以根据 filterArray 值测试 Objects 值。 If any of the attribute values match the filterArray values, then we can include the doctor in the resulting filteredDoctors list.如果任何属性值与 filterArray 值匹配,那么我们可以将医生包含在结果过滤医生列表中。

const Results = () => {
  const filterArray = useSelector((state) => state.filterArray);
  const doctors = useSelector((state) => state.doctors);

  const filteredDoctors = useMemo(() => {
    return doctors.filter((doctor) => {
      return filterArray.some((filter) => {
        return Object.values(doctor).some((value) => value === filter);
      });
    });
  }, [doctors, filterArray]);

  return filteredDoctors.map((doctor) => <span>{doctor}</span>);
};

Update:更新:

After discussion in chat:在聊天中讨论后:

const Results = () => {
  const filterArray = useSelector((state) => state.filterArray);
  const doctors = useSelector((state) => state.doctors);

  const filteredDoctors = useMemo(() => {
    return doctors.filter((doctor) => {
      return filterArray.some((filter) => {
        return Object.values(doctor).some((value) => {
          // If the attribute value is an array
          if (Array.isArray(value)) {
            return value.some((value) => value === filter);
          }
          // If the attribute value is an object, get the values from the object
          if (typeof value === 'object') {
            return Object.values(value).some((value) => value === filter);
          }
          // By default, expect the value to be a string
          return value === filter;
        });
      });
    });
  }, [doctors, filterArray]);

  return filteredDoctors.map((doctor) => <span>{doctor}</span>);
};

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

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