Filter the object based on the nested array object

Viewed 93

Recently, I gave an interview and rejected there were about 10 questions. Each question had 60 seconds. There was a question that went wrong but I was curious why it happened.

I have to filter those objects in which given SearchValue match with the list array object name property. The search value was already given.

For example:

const SearchValue = 'event';

It is filtered array because list[0].name property value match with the the event text.

const res = [
    {
        id: 2,
        name: 'Events',
        list: [
            {
                id: 1,
                name: 'Event Ticketing System',
                slug: '/'
            },
            {
                id: 2,
                name: 'Events Management Software',
                slug: '/'
            }
        ]
    }
]; 

The name property contains value something like this Online Translation Services and Spelling and Grammar Check etc. If the search value match with the text then save it those filtered objects and console.log. The data-set was something like this.

const listing = [
  {
    id: 1,
    name: 'Language',
    list: [
      {
        id: 1,
        name: 'Online Translation Services',
        slug: '/'
      },
      {
        id: 2,
        name: 'Spelling and Grammar Check',
        slug: '/'
      },
      {
        id: 3,
        name: 'TEFL Courses',
        slug: '/'
      },
      {
        id: 4,
        name: 'Language Learning',
        slug: '/'
      }
    ]
  },
  {
    id: 2,
    name: 'Events',
    list: [
      {
        id: 1,
        name: 'Event Ticketing System',
        slug: '/'
      },
      {
        id: 2,
        name: 'Events Management Software',
        slug: '/'
      }
    ]
  }
];

My implementation was this.

const SearchValue = 'event';

const listing = [{
    id: 1,
    name: 'Language',
    list: [{
        id: 1,
        name: 'Online Translation Services',
        slug: '/'
      },
      {
        id: 2,
        name: 'Spelling and Grammar Check',
        slug: '/'
      },
      {
        id: 3,
        name: 'TEFL Courses',
        slug: '/'
      },
      {
        id: 4,
        name: 'Language Learning',
        slug: '/'
      }
    ]
  },
  {
    id: 2,
    name: 'Events',
    list: [{
        id: 1,
        name: 'Event Ticketing System',
        slug: '/'
      },
      {
        id: 2,
        name: 'Events Management Software',
        slug: '/'
      }
    ]
  }
];

const res = listing.filter(object => {
  if (Array.isArray(object.list) && object.list.length > 0) {
    return object.list.filter((item) => {
      return item.name.toLowerCase().indexOf(SearchValue.toLowerCase()) !== -1;
    });
  }
});


console.log('Result Array', res);

If anyone can provide a good solution really appreciated. I also want to know What was wrong with this logic?

3 Answers

You can use Array#filter along with Array#some to verify if any of the elements of the list property of each object contains the search text in its name.

const listing = [ { id: 1, name: 'Language', list: [ { id: 1, name: 'Online Translation Services', slug: '/' }, { id: 2, name: 'Spelling and Grammar Check', slug: '/' }, { id: 3, name: 'TEFL Courses', slug: '/' }, { id: 4, name: 'Language Learning', slug: '/' } ] }, { id: 2, name: 'Events', list: [ { id: 1, name: 'Event Ticketing System', slug: '/' }, { id: 2, name: 'Events Management Software', slug: '/' } ] } ];
const SearchValue = 'event';
const res = listing.filter(({list})=>
 list.some(({name})=>name.toLowerCase().includes(SearchValue.toLowerCase())));
console.log(res);

Check with RegEx and test

const SearchValue = 'event';

const listing = [{
    id: 1,
    name: 'Language',
    list: [{
        id: 1,
        name: 'Online Translation Services',
        slug: '/'
      },
      {
        id: 2,
        name: 'Spelling and Grammar Check',
        slug: '/'
      },
      {
        id: 3,
        name: 'TEFL Courses',
        slug: '/'
      },
      {
        id: 4,
        name: 'Language Learning',
        slug: '/'
      }
    ]
  },
  {
    id: 2,
    name: 'Events',
    list: [{
        id: 1,
        name: 'Event Ticketing System',
        slug: '/'
      },
      {
        id: 2,
        name: 'Events Management Software',
        slug: '/'
      }
    ]
  }
];

const res = listing.filter(object => {
  if (Array.isArray(object.list) && object.list.length > 0) {
    // Check items with RegEx test
    // and update object.list
    object.list = object.list.filter(item => new RegExp(SearchValue, 'i').test(item.name));
    // Return true if list length > 0
    if(object.list.length > 0) return true;
  }
});


console.log('Result Array', res);

Array Filter

let newArray = arr.filter(callback(element[, index, [array]])[, thisArg])

callback

Function is a predicate, to test each element of the array. Return true to keep the element, false otherwise.

Return value

A new array with the elements that pass the test. If no elements pass the test, an empty array will be returned.

const SearchValue = 'language';

const listing = [{
    id: 1,
    name: 'Language',
    list: [{
        id: 1,
        name: 'Online Translation Services',
        slug: '/'
      },
      {
        id: 2,
        name: 'Spelling and Grammar Check',
        slug: '/'
      },
      {
        id: 3,
        name: 'TEFL Courses',
        slug: '/'
      },
      {
        id: 4,
        name: 'Language Learning',
        slug: '/'
      }
    ]
  },
  {
    id: 2,
    name: 'Events',
    list: [{
        id: 1,
        name: 'Event Ticketing System',
        slug: '/'
      },
      {
        id: 2,
        name: 'Events Management Software',
        slug: '/'
      }
    ]
  }
];

const res = listing.reduce((pre, object) => {
  if(!Array.isArray(object.list) || object.list.length <= 0)
    return pre
  
  object.list = object.list.filter((item) =>  item.name.toLowerCase().indexOf(SearchValue.toLowerCase()) > -1);
    
  return object.list.length > 0 ? [...pre, object] : pre;

}, []);


console.log('Result Array', res);

Related