Home > Blockchain >  How to implement a Search inside a Nested Array of Objects?
How to implement a Search inside a Nested Array of Objects?

Time:05-22

I want to implement a keyword search for a field which is located inside Nested Array of Objects. How can I achieve it?

Data -

const groupList = [{
 "group_name": "General",
 "trainings": [
    {
        "id": 1,
        "training_name": "Plural Sight",
    },
    {
        "id": 2,
        "training_name": "Google Maps",
    }
 ]
}]

Code -

const [groupsData, setGroupsData] = useState([]);

const lowerContains = (str1, str2) => str1 && str2 && str1.toLowerCase().indexOf(str2.toLowerCase()) !== -1;

const handleSearch = searchKeyword => {
    if (searchKeyword && searchKeyword.trim()) {
      const groupFiltered = groupList.filter(item => item.group_name && lowerContains(item.group_name, searchKeyword));
      setGroupsData( groupFiltered );
      return;
    }
    setGroupsData({ [...groupList] });
};

Currently I am able to search with group_name but I want to also search with training_name inside trainings.

CodePudding user response:

Assuming you want to keep the group object if the searchKeyword is contained within the group name OR one of the training name objects, you can use .some(). By using .some() on trainings, you can check if there is at least one object within the trainings array that contains a training_name value that matches your keyword search:

const groupFiltered = groupList.filter(item => 
  (item.group_name && lowerContains(item.group_name, searchKeyword)) ||
  (item.trainings.some(training => lowerContains(training.training_name, searchKeyword)))
);

Note: In the example data you shared, group_name always contains a value, so you can remove the item.group_name && check if that is always the case.

See working example below:

const groupList = [{ "group_name": "General", "trainings": [{ "id": 1, "training_name": "Plural Sight", }, { "id": 2, "training_name": "Google Maps", } ] }];
const lowerContains = (x, y) => x.toLowerCase().includes(y.toLowerCase());

const searchKeyword = "Plural";
const groupFiltered = groupList.filter(item => 
  (item.group_name && lowerContains(item.group_name, searchKeyword)) ||
  (item.trainings.some(training => lowerContains(training.training_name, searchKeyword)))
);

console.log(groupFiltered);

CodePudding user response:

You can search inside the trainings if group_name is not matched using Array.prototype.some() operation on the trainings.

Try like below.

  const handleSearch = (searchKeyword) => {
    if (searchKeyword && searchKeyword.trim()) {
      const groupFiltered = groupList.filter(
        (item) =>
          (item.group_name && lowerContains(item.group_name, searchKeyword)) ||
          item.trainings.some(({ training_name }) =>
            lowerContains(training_name, searchKeyword)
          )
      );
      setGroupsData(groupFiltered);
      return;
    }
    setGroupsData(groupList);
  };

CodePudding user response:

You can use javascript's "Array.some" method.

const containsTraining = (item, keyword) => {
  return item.some(
    (training) =>
      training.training_name && lowerContains(training.training_name, keyword)
  );
};

This will return true if item (one single group) contains at least one training that has the training name search keyword.

  • Related