Home > Software design >  Filtering an object by multiple arguments(inputs)
Filtering an object by multiple arguments(inputs)

Time:11-10

I have a lot of inputs, after which my object is supposed to filter, I can hardcode it, but there is probably a smarter way to do it

Filter state :

  const [filters, setFilters] = useState<FiltersType>({
    login: "",
    name: "",
    surrname: "",
  });

Example data:

const data: UserRow[] = [
 
  {
    key: "1",
    login: "[email protected]",
    name: "John",
    surrname: "Smith",
    role: ["user"],
  },
  {
    key: "2",
    login: "[email protected]",
    name: "Andrew",
    surrname: "Johnson",
    role: ["user"],
  },

];
data.filter((e) => {
              if (
                (!filters.name || e.name.includes(filters.name)) &&
                (!filters.surrname || e.surrname.includes(filters.surrname)) &&
                (!e.login ||
                  e.login.toLowerCase().includes(filters.login.toLowerCase()))
              ) {
                return true;
              }
              return false;
            })

For example, it can be done like this, but as you can see it looks bad and scales poorly when adding new fields, I tried to simplify it using "Object.entries()", but ultimately failed :(. What is the best pattern for such a problem?

CodePudding user response:

You should use some() (logical OR for all the conditions) or every() (logical AND for all the conditions) in combination with filter().

const data = [
  {
    key: "1",
    login: "[email protected]",
    name: "John",
    surrname: "Smith",
    role: ["user"],
  },
  {
    key: "2",
    login: "[email protected]",
    name: "Andrew",
    surrname: "Johnson",
    role: ["user"],
  },
];

const filter = {
  login: "",
  name: "",
  surrname: "",
};
const filters = Object.entries(filter);
const filtered = data.filter((user) =>
  filters.some(
    ([key, value]) =>
      user[key] && user[key].toString().toLowerCase().includes(value)
  )
);

console.log(filtered);

Use some() if you want to include the result if any of the filter conditions is met and use every() if you want to only include a result if all filter conditions are met.

The above will work for simple filters. You can however extend the solution using typeof() or Array.isArray() function etc. to process different types like arrays, nested objects etc. accordingly.

  • Related