its me
its me

Reputation: 542

How do I filter an array of objects inside of an array of objects Using javascript?

I have below an array called data:

const data = [
         {id:1 ,name: 'Product A', image: 'pic-001.jpg', tags: [{id:50 ,productname: 'Test A'}]},
         {id:2 ,name: 'Product B', image: 'pic-002.jpg', tags: [{id:60,productname: 'Test A'}]},
         {id:3 ,name: 'Product C', image: 'pic-003.jpg', tags: [{id:70,productname: 'Test B'}]}
       ]
       
//I have an array of objects. Inside these objects, there is another array: tags. 
//My question is, how would I filter the multiple fields inside the data array 

 
//if I filtered by, e.g., a id:1, I'd receive the following returned:
   var output1 =   [{id:1 ,name: 'Product A', image: 'pic-001.jpg', tags: [{id:50 ,productname: 'Test A'}]}]

  
// if I filtered by, e.g., a productname: 'Test A', I'd receive the following returned:
var output2 = [  {id:1 ,name: 'Product A', image: 'pic-001.jpg', tags: [{id:50 ,productname: 'Test A'}]}, {id:2 ,name: 'Product B', image: 'pic-002.jpg', tags: [{id:60,productname: 'Test A'}]}]

//I have tried the below code but it's not working 

    const filter = '1';
    //const filter = 'Test A';
    const Result = data.filter((item) => {
        return (
        item.id.toString().indexOf(filter) > -1 ||item.tags.indexOf(filter) > -1 
        );
    });
    
    console.log(Result)

Upvotes: 0

Views: 79

Answers (3)

Nithish
Nithish

Reputation: 6039

Since the tags is an array of objects inside each product object, we can make use of Array.some and find if any of the tag's productname is matching with the required value that we are looking for

const data = [
     {id:1 ,name: 'Product A', image: 'pic-001.jpg', tags: [{id:50 ,productname: 'Test A'}]},
     {id:2 ,name: 'Product B', image: 'pic-002.jpg', tags: [{id:60,productname: 'Test A'}]},
     {id:3 ,name: 'Product C', image: 'pic-003.jpg', tags: [{id:70,productname: 'Test B'}]}
];

const getFilteredData = (data, value) => data.filter(datum =>
  datum.id.toString().includes(value.toString()) || datum.tags.some(tag => tag.productname.includes(value))
);

console.log(getFilteredData(data, 1));
console.log(getFilteredData(data, 'Test A'));
console.log(getFilteredData(data, 'Test B'));
.as-console-wrapper {
  max-height: 100% !important;
}

Upvotes: 1

Sajeeb Ahamed
Sajeeb Ahamed

Reputation: 6418

You can create respective functions for filtering the array. Say I've created two functions filterByTag(key, value) and filterBy(key, value).

In the filterByTag function, provide two arguments key & value. Where the key is the object key inside the tags array.

This is similar to the filterBy function. The fitlerBy is applied directly to the data array.

const data = [
  {id:1, name: 'Product A', image: 'pic-001.jpg', tags: [{id:50, productname: 'Test A'}]},
  {id:2, name: 'Product B', image: 'pic-002.jpg', tags: [{id:60, productname: 'Test A'}]},
  {id:3, name: 'Product C', image: 'pic-003.jpg', tags: [{id:70, productname: 'Test B'}]}
];

const filterByTag = (key, value) => data.filter(item => item.tags.find(x => x[key] === value));
const filterBy = (key, value) => data.filter(item => item[key] === value);

console.log(filterByTag('productname', 'Test A'));
console.log(filterByTag('id', 60));
console.log(filterBy('id', 1));
console.log(filterBy('name', 'Product A'));
.as-console-wrapper{min-height: 100%!important; top: 0}

Upvotes: 1

Nick Parsons
Nick Parsons

Reputation: 50954

Using .indexOf() on an array of objects to check for a string value (eg: 'Test A') won't work, as your string doesn't equal an object within your array. Instead, you can use .some() to specify the search logic using its callback and return true once you find a product_name that equals your filter:

const data = [{ id: 1, name: 'Product A', image: 'pic-001.jpg', tags: [{ id: 50, productname: 'Test A' }] }, { id: 2, name: 'Product B', image: 'pic-002.jpg', tags: [{ id: 60, productname: 'Test A' }] }, { id: 3, name: 'Product C', image: 'pic-003.jpg', tags: [{ id: 70, productname: 'Test B' }] } ];

//const filter = '1';
const filter = 'Test A';
const Result = data.filter((item) => 
  item.id.toString().includes(filter) || item.tags.some(item => item.productname === filter)
);

console.log(Result)

I've also updated your .indexOf() call on your first string/id to use .includes(), which is a more modern way to check whether your string contains a value.

Upvotes: 1

Related Questions