0

I have the following data array that I wanna filter by company name/names.

data = [
   {
      "company":{
         "name":"Company 1",
         "symbol":"one"
      },
      "description":"test",
      "status":"Pending"
   },
   {
      "company":{
         "name":"Company 2",
         "symbol":"two"
      },
      "description":"test",
      "status":"Pending"
   },
   {
      "company":{
         "name":"Company 3",
         "symbol":"three"
      },
      "description":"test",
      "status":"Pending"
   },
   {
      "company":{
         "name":"Company 1",
         "symbol":"four"
      },
      "description":"testrr",
      "status":"Pending"
   }
]
filterBy = ["Company 1", "Company 3"]

Expected Result

filteredData = [
   {
      "companyName":"Company 1",
      "matchingData":[
         {
            "company":{
               "name":"Company 1",
               "symbol":"one"
            },
            "description":"test",
            "status":"Pending"
         },
         {
            "company":{
               "name":"Company 1",
               "symbol":"four"
            },
            "description":"testrr",
            "status":"Pending"
         }
      ]
   },
   {
      "companyName":"Company 3",
      "matchingData":[
         {
            "company":{
               "name":"Company 3",
               "symbol":"three"
            },
            "description":"test",
            "status":"Pending"
         }
      ]
   }
]

Attempted

using the the following attempt I am getting all the matching objects instead of each match individually

const result = data.filter((obj) => filterBy.includes(obj.company.name));
let expectedResult = []
 filterBy.forEach((e, i )=> {
      let d = {companyName:e[i], matchingData: result}
      expectedResult .push(d)
    });

...................................................................................................................................................................

1
  • 1
    (After your edit - which is a bummer since you already got two answers on a totally different sample an desired output...) I would suggest for a far better output, and that's an Objectwhere the keys are the actualy company names (since those are anyways unique!) {"Company 1": [{}, {}], "Company 3": [{}]} the code necessary to create such an output would be a nobrainer. Commented Jul 21, 2021 at 4:40

3 Answers 3

1

Since you changed the Question desired output on the fly - I guess you're not strictly enforcing that exact output - therefore here's a far better one.

I would suggest for a far better output, and that's an Object - where the keys are the actually company names (since those are anyways unique!) {"Company 1": [{}, {}], "Company 3": [{}]} the code necessary to create such an output would be a nobrainer thanks to Array.prototype.reduce()

const data = [{"company":{"name":"Company 1","symbol":"one"},"description":"test","status":"Pending"},{"company":{"name":"Company 2","symbol":"two"},"description":"test","status":"Pending"},{"company":{"name":"Company 3","symbol":"three"},"description":"test","status":"Pending"},{"company":{"name":"Company 1","symbol":"four"},"description":"testrr","status":"Pending"}];

const filterBy = ["Company 1", "Company 3"];

const filteredData = data.reduce((ob, data) => {
  const n = data.company.name;
  if (filterBy.includes(n)) {
    if (!ob[n]) ob[n] = [];
    ob[n].push(data);
  }
  return ob;
}, {});

console.log(filteredData); // {"Company 1": [{..}, {..}], "Company 3", [{..}]}

The beauty of the above is that later you can easily extract the desired list using:

const items_of_comp_1 = filteredData["Company 1"];
console.log(items_of_comp_1); // [{...}, {...}]

Or if you want to loop the filteredData Object you can do it super easily using: Object.entries(), Object.keys() or Object.values() methods!


Old answer before your edit

You were pretty close, but .forEach() and .map() are not meant to create subsets. .filter() is also out of the game since you want a slightly modified output. Therefore use .reduce():

  • Use Array.prototype.reduce() to reduce an array to a filtered but modified set of items
  • Use Array.prototype.includes() (which you already do use) to check whether an array includes a specific item

const data = [{"company":{"name":"Company 1","symbol":"one"},"description":"test","status":"Pending"},{"company":{"name":"Company 2","symbol":"two"},"description":"test","status":"Pending"},{"company":{"name":"Company 3","symbol":"three"},"description":"test","status":"Pending"}];
const filterBy = ["Company 1", "Company 3"]

const filteredData = data.reduce((a, matchingData) => {
  const companyName = matchingData.company.name;
  if (filterBy.includes(companyName)) a.push({companyName, matchingData});
  return a;
}, []);

console.log(filteredData)

Sign up to request clarification or add additional context in comments.

1 Comment

You are beyond awesome! really appreciate it!
1

The matchingData property in each output item needs to be not the result, which is the whole filtered array, but an array with a single element in it, where that element is the filtered item being iterated over.

You can also use .map instead of .push to make things a bit cleaner.

data = [
   {
      "company":{
         "name":"Company 1",
         "symbol":"one"
      },
      "description":"test",
      "status":"Pending"
   },
   {
      "company":{
         "name":"Company 2",
         "symbol":"two"
      },
      "description":"test",
      "status":"Pending"
   },
   {
      "company":{
         "name":"Company 3",
         "symbol":"three"
      },
      "description":"test",
      "status":"Pending"
   }
]
filterBy = ["Company 1", "Company 3"]

const result = data
  .filter((obj) => filterBy.includes(obj.company.name))
  .map(item => ({
    companyName: item.company.name,
    matchingData: [item]
  }));
console.log(result);

If multiple items in the input array may have the same company, and those same companies should be grouped in the output - eg

filteredData = [
   {
      "companyName":"Company 1",
      "matchingData":[
          <some company 1 object>,
          <some other company 1 object>,

then you'll need to be a bit more elaborate. Make an object whose keys are the companyName and values are the arrays.

data = [
   {
      "company":{
         "name":"Company 1",
         "symbol":"one"
      },
      "description":"test",
      "status":"Pending"
   },
   {
      "company":{
         "name":"Company 2",
         "symbol":"two"
      },
      "description":"test",
      "status":"Pending"
   },
   {
      "company":{
         "name":"Company 3",
         "symbol":"three"
      },
      "description":"test",
      "status":"Pending"
   }
]
filterBy = ["Company 1", "Company 3"]

const filtered = data.filter((obj) => filterBy.includes(obj.company.name));
const grouped = {};
for (const item of filtered) {
  const { name } = item.company;
  grouped[name] ??= [];
  grouped[name].push(item);
}
const result = Object.entries(grouped).map(
  ([companyName, matchingData]) => (
    { companyName, matchingData }
  ));
console.log(result);

2 Comments

I just edited my data: 'Company 1' might have more than one matching item, and I want them all in the same array. Sorry for not explaining it correctly
Then use the code in the second part of the answer
-1

Here is your code I filter for company 1 and company 3

https://codepen.io/tmixab/pen/poPrxWJ

data = [
   {
      "company":{
         "name":"Company 1",
         "symbol":"one"
      },
      "description":"test",
      "status":"Pending"
   },
   {
      "company":{
         "name":"Company 2",
         "symbol":"two"
      },
      "description":"test",
      "status":"Pending"
   },
   {
      "company":{
         "name":"Company 3",
         "symbol":"three"
      },
      "description":"test",
      "status":"Pending"
   }
]

filterBy = ["Company 1", "Company 3"];

const result = data.filter((obj) => filterBy.includes(obj.company.name));

console.log(JSON.stringify(result, null, 4));

/*
let expectedResult = []
 filterBy.forEach((e, i )=> {
      let d = {companyName:e[i], matchingData: result}
      expectedResult.push(d)
    });
*/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.