2

I want to be able to filter an array of data by multiple parameters:

const data = [{
    userId: '7',
    id: '1',
    title: 'quo provident culpa',
    body: "a",
    completed: true
  },
  {
    userId: '7',
    id: '2',
    title: 'natus commodi et',
        body: "a",
    completed: true
  },
  {
    userId: '1',
    id: '3',
    title: 'voluptatem et reprehenderit',
    body: "c",
    completed: false
  }
];

const query = {
  title: 'l',
  body: 'a'
}

I've tried this:

const filterData = (data, query) => {
  return data.filter(rec => {
    return Object.keys(query)
      .find(key => rec[key] === query[key])
  })
}

console.log(filterData(data, query))

My solution is not quite working since it returns any objects that satisfy at least one parameter. In the case above I get this returned:

[{
  body: "a",
  completed: true,
  id: "1",
  title: "quo provident culpa",
  userId: "7"
}, {
  body: "a",
  completed: true,
  id: "2",
  title: "natus commodi et",
  userId: "7"
}]

but what I really wanted was to get returned only what satisfies both conditions (title and body) by partially match the string. like so:

{
  userId: '7',
  id: '1',
  title: 'quo provident culpa',
  completed: true
}

I understand that the find() method returns the first element that satisfies a condition, but this was the closest I could get since I want it to

2 Answers 2

9

You could filter with Array#every for the wanted parameters and check only with String#includes.

const
    data = [{ userId: '7', id: '1', title: 'quo provident culpa', body: "a", completed: true }, { userId: '7', id: '2', title: 'natus commodi et',  body: "a", completed: true }, { userId: '1', id: '3', title: 'voluptatem et reprehenderit', body: "c", completed: false }],
    query = { title: 'l', body: 'a' },
    filterData = (data, query) => data.filter(rec => Object
        .entries(query)
        .every(([k, v]) => rec[k].toString().includes(v))
    );

console.log(filterData(data, query));

Sign up to request clarification or add additional context in comments.

Comments

3

If you only need the first occurrence just replace filter with find.

const filterData = (data, query) => {
  return data.find(rec => {
    return Object.keys(query)
      .find(key => rec[key] === query[key])
  })
}

Edit: You could combine filter with every like this:

const filterData = (data, query) => {
  return data.filter((item) => {
    return Object.keys(query).every((key) => {
      return (item[key] + '').includes(query[key] + '');
    }, true);
  });
}

4 Comments

There is no objects with title: 'l'. You need to check if the string is included, not ===
what happens when he got two entries satisfying the query ?
I've updated my answer but the implementation was already answered.
There are still some caveats with number or boolean values in my answer toString() ensures that won't fail.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.