Etoya
Etoya

Reputation: 239

Object inside array inside object inside array JavaScript - Search

I have a data like this:

   const bigData = [
  {
    id: '1',
    data: [
      {category: 'swim', value: 'Abc'},
      {category: 'ran', value: '123'},
      {category: 'play', value: 'Test'}
    ]
  },
  {
    id: '2',
    data: [
      {category: 'swim', value: 'Abc'},
      {category: 'ran', value: ''},
      {category: 'play', value: 'abc'}
    ]
  },
  {
    id: '3',
    data: [
      {category: 'swim', value: 'String that I Need'},
      {category: 'ran', value: '456'},
      {category: 'play', value: 'Testtest'}
    ]
  }
]

I want to get array of objects if one of this objects contains part of the string in their value.

For example, if the search string is "String tha" it should return

   [ {
    id: '3',
    data: [
      {category: 'swim', value: 'String that I Need'},
      {category: 'ran', value: '456'},
      {category: 'play', value: 'Testtest'}
    ]
  }]

And if the search string is "Abc" it should return

[{
        id: '1',
        data: [
          {category: 'swim', value: 'Abc'},
          {category: 'ran', value: '123'},
          {category: 'play', value: 'Test'}
        ]
      },
      {
        id: '2',
        data: [
          {category: 'swim', value: 'somethinf'},
          {category: 'ran', value: ''},
          {category: 'play', value: 'Abcd'}
        ]
      },]

This is what I have so far, not sure if it is even the right direction to go:

const arr = bigData.map(
      (item) => item.data
    )
    const res = arr
      ?.map((item) => item.map((e) => e.value))
      .filter((i) => i.map((e) => e.includes(search) === true))

Upvotes: 2

Views: 2993

Answers (2)

Patrick Roberts
Patrick Roberts

Reputation: 51816

There's no reason to map() the outer array to each object's data member, since the return value and the input value have the same layout. Instead, you're performing a filter() on the outer array bigData, which should keep objects whose inner array member data satisfies a certain condition.

You can check for that condition using some(), since it is applied to each element of the array, and you only care whether or not there exists an element that matches.

function filterBySearch (search) {
  return bigData.filter(
    ({ data }) => data.some(
      ({ value }) => value.includes(search)
    )
  );
}

const bigData = [
  {
    id: '1',
    data: [
      {category: 'swim', value: 'Abc'},
      {category: 'ran', value: '123'},
      {category: 'play', value: 'Test'}
    ]
  },
  {
    id: '2',
    data: [
      {category: 'swim', value: 'Abc'},
      {category: 'ran', value: ''},
      {category: 'play', value: 'abc'}
    ]
  },
  {
    id: '3',
    data: [
      {category: 'swim', value: 'String that I Need'},
      {category: 'ran', value: '456'},
      {category: 'play', value: 'Testtest'}
    ]
  }
];

console.log(filterBySearch('String tha'));
console.log(filterBySearch('Abc'));
.as-console-wrapper{max-height:100%!important;}

Upvotes: 5

musicfuel
musicfuel

Reputation: 1680

The easiest approach is the one liner already provided by Patrick. You are on the right path, but just getting tripped up on the proper use of the array functions. If you wanted to write this as a function, it would look like:

function searchBigData(bigData, searchText) {
    return bigData.filter(entry => entry.data.some(item => item.value.includes(searchText)));
}

For future reference, the basic strategy here is:

  1. Use filter on the bigData array because you want to reduce that down to the original objects that meet your criteria.
  2. For each item in bigData, use some against the data array. It will return true as soon as one of the items in data matches the condition.
  3. Test each item in data for the value to include the search text

Upvotes: 3

Related Questions