Home > Software engineering >  Find the search keyword in nesting array of objects
Find the search keyword in nesting array of objects

Time:08-19

 let arr = [
      {
        id:{key:1, name:"apple"},
        fruits:[{id:{key:1.1,name:"green apple"}},{id:{key:1.2, name: "red apple"}}]
      },
      {
        id:{key:2, name:"grapes"},
        fruits:[{id:{key:2.1,name:"green grapes"}},{id:{key:2.2, name: "black grapes"}}]
      },
      {
        id:{key:3, name:"berries"},
        fruits:[{id:{key:3.1,name:"strawberries"}},{id:{key:3.2, name: "blueberries"}}]
      },
      {
        id:{key:4, name:"banana"},
        fruits:[{id:{key:4.1,name:"yellow banana"}}]
      }
    ]

const search = "pp"

    function filterResult(obj) {
      const re = new RegExp(search, "ig")
      return re.test(obj.id.name)
    }

    //this gives result of outer id array only 
   const searchResult = [
...Object.values(arr).filter((v) => {  
     let tempArr = [];
      if (filterResult(v)) {
        tempArr.push(v);
         return [...tempArr,...(v.fruits).filter((vv) => {
            return filterResult(vv);
          })]    
      }
    })
].map((res)=>res.id);

console.log(searchResult);

But now how to search in nested array (fruits) of arr I tried to use flatMap, but I feel i did something wrong.

const searchResult = [
...Object.values(arr).filter((v) => {  
     let tempArr = [];
      if (filterResult(v)) {
        tempArr.push(v);
         return [...tempArr,...(v.fruits).filter((vv) => {
             filterResult(vv);
          })]    
      }
    })
]

I want "search Result" result like : because they pp keyword in all ( parent child on same level)

[{id:1, name: "apple"}, {id:1.1,name:"green apple"},{id:1.2, name: "red apple"}]

PS: not allowed to use flatMap

CodePudding user response:

Solution

/**
 * Sample data provided.
 */
const arr = [
  {
    id: { id: 1, name: 'apple' },
    fruits: [{ id: 1.1, name: 'green apple' }, { id: 1.2, name: 'red apple' }]
  },
  {
    id: { id: 2, name: 'grapes' },
    fruits: [{ id: 2.1, name: 'green grapes' }, { id: 2.2, name: 'black grapes' }]
  },
  {
    id: { id: 3, name: 'berries' },
    fruits: [{ id: 3.1, name: 'strawberries' }, { id: 3.2, name: 'blueberries' }]
  },
  {
    id: { id: 4, name: 'banana' },
    fruits: [{ id: 4.1, name: 'yellow banana' }]
  }
];

/**
 * Find all fruits whose name contains the query.
 *
 * @param {*} array items to iterate through
 * @param {*} query search query
 * @returns {Array} array of objects whose property name contains the query
 */
const search = (array, query) => {
  /**
   * MDN documentation on Array.prototype.reduce
   * ------------------------------------------------------
   * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
   * ------------------------------------------------------
   */
  return array.reduce((acc, item) => {
    return [
      ...acc,
      /**
       * Add the item to the accumulator if the item name contains the query.
       */
      ...item.id.name.includes(query) ? [item.id] : [],
      /**
       * Add all fruits whose name contains the query to the accumulator.
       */
      ...item.fruits.filter(fruit => fruit.name.includes(query))]
  }, []);
};

console.log(search(arr, 'pp'));

Output

[
  { id: 1, name: 'apple' },
  { id: 1.1, name: 'green apple' },
  { id: 1.2, name: 'red apple' }
]

CodePudding user response:

A call of filter on the input array can only return top level objects, never inner objects. Moreover, it is not necessary to call Object.values on an array. Just iterate the array.

I would use a recursive generator for this purpose. This way you can have input that is even deeper nested with objects:

function* filterRec(arr, re) {
    for (const {fruits, ...obj} of arr) {
        if (re.test(obj.name)) yield obj;
        if (re.test(obj.id?.name)) yield obj.id;
        if (fruits) yield* filterRec(fruits, re);
    }
}

const filter = (arr, search) => [...filterRec(arr, RegExp(search, "i"))];

// Demo
const arr = [{id:{id:1, name:"apple"},fruits:[{id:1.1,name:"green apple"},{id:1.2, name: "red apple"}]},{id:{id:2, name:"grapes"},fruits:[{id:2.1,name:"green grapes"},{id:2.2, name: "black grapes"}]},{id:{id:3, name:"berries"},fruits:[{id:3.1,name:"strawberries"},{id:3.2, name: "blueberries"}]},{id:{id:4, name:"banana"},fruits:[{id:4.1,name:"yellow banana"}]}];
const search = "pp"
const searchResult = filter(arr, search);
console.log(searchResult);

  • Related