0

I have an array of objects called 'infos', within this array of objects i have an element called TagId. I have another array called 'TagIds' which holds 0 - 3 ids at any one given time. I want to loop through each object within my 'infos' array and if there is a match add the object to my 'filteredResults' array.

Now i have achieved this by the following code:

  infos: Array<{InfoPageId: number, DepartmentId: number, Name: string, Url: string, Html: string, Title: string, Keywords: string, Description: string, InfoTypeId: number, DateCreated: Date, DateUpdated: Date, Hidden: boolean, AMPhtml: string, UseAmp: boolean, UseAmpVideo: boolean, UseCarousel: boolean, TradeOnly: boolean, TagId: number}> = [];

  TagIds = []; 

 getBuyingGuidesNotFiltered() {
   this.IsWait = true;
   this._SharedService.getAll().subscribe((data: any[]) => {
     data.forEach(e => {
       if(e.InfoTypeId === 12)
       {
         this.infos.push(new infoPage(
          e.InfoPageId, 
          e.DepartmentId, 
          e.Name, 
          e.Url, 
          e.Html,
          e.Title, 
          e.Keywords,
          e.Description, 
          e.InfoTypeId, 
          e.DateCreated, 
          e.DateUpdated, 
          e.Hidden, 
          e.AMPhtml,
          e.UseAmp, 
          e.UseAmpVideo, 
          e.UseCarousel,
          e.TradeOnly,
          e.TagId
        )); 
      }        
   })
   this.getFiltered(this.infos);
   this.IsWait = false;
 }); 
}

  getFiltered(infos: Array<infoPage>) {
    var filteredResults = []
    for(var i = 0; i < this.infos.length; i++) {
      for(var j = 0; j < this.TagIds.length; j++) {
        if(this.infos[i].TagId === this.TagIds[j]) {
          filteredResults.push(this.infos[i]);  
        }
      }
    }
    this.infos = [];
    this.infos = filteredResults;
  }

Now the problem is that my object array 'infos' holds duplicate data for example:

this.infos = [ 
{InfoPageId: 8, DepartmentId: 1, Name: "Pitched Roof Window Buying Guide", Url: "buying-guide-pitched", TagId: 15"}
{InfoPageId: 8, DepartmentId: 1, Name: "Pitched Roof Window Buying Guide", Url: "buying-guide-pitched", TagId: 12"}
]

however as you can see the TagId is different.

I want to be able to loop through my 'infos' array and only add the object once to my 'filteredResults' array but also only add that object when the TagId for each object with the same 'InfoPageId' exists in the 'Tagids' array. for example if the objects with a 'InfoPageId' of 8 have a TagId of 12 and 15 and the 'TagIds' arrays has the values 12 and 15 then add the object to the 'filteredResults' array however if the Object only contains a TagId of 12 but the 'TagIds' array has the values 12 and 15 dont add.

example of desired output;

Input:

TagIds = [10, 5]

infos = [
{InfoPageId: 11, DepartmentId: 1, Name: "Flat Roof Window Buying Guide", Url: "buying-guide-rooflights", Tagid: 10"}
{InfoPageId: 11, DepartmentId: 1, Name: "Flat Roof Window Buying Guide", Url: "buying-guide-rooflights", Tagid: 5"}
{InfoPageId: 12, DepartmentId: 1, Name: "Flat Roof Window Buying Guide", Url: "buying-guide-rooflights", Tagid: 10"}
]

output:

filteredResults = [
{InfoPageId: 11, DepartmentId: 1, Name: "Flat Roof Window Buying Guide", Url: "buying-guide-rooflights", Tagid: 10"}
]

Hope you guys can understand this. Its pretty hard to explain.

5
  • 3
    You really should give examples of inputs and desired outputs Commented Jun 10, 2020 at 13:25
  • 1
    well, I actually understood your question, but don't have the time to write a code for this. the general idea is to do it as you did (maybe with a filter func and indexOf or includes funcs). afterwards I would build a map of the InfoPageId: [TagID], and then filter out those that not in the required criteria. afterwards you easily can filter the original array with whatever left. hope you got my answer Commented Jun 10, 2020 at 13:28
  • Updated with your recommendations for example input/ouput Commented Jun 10, 2020 at 13:50
  • By the example you posted I assume you want the filtered results to match all the TagIds. Is that it? Commented Jun 10, 2020 at 13:54
  • Yes that is correct. I know how to remove the duplicates but not sure how to do that logic Commented Jun 10, 2020 at 13:56

1 Answer 1

1

Try this:

  getFiltered(infos: any) {
    // reduces every row to a pair containing InfoPageId: [all TagIds]
    let reduced = infos.reduce((acc, v) =>
      (acc[v.InfoPageId] = [...acc[v.InfoPageId] || [], v.TagId], acc), {}
    );
    // finds all pageIds that match every existing TagId
    let fullTagMatchedIds = Object.keys(reduced).filter(
      key => this.TagIds.reduce((acc, tag) => acc && reduced[key].includes(tag), true)
    );
    // retrieves first row of each pageId that matched all TagIds
    let filteredResults = fullTagMatchedIds
      .map(infoId => infos.find(info => info.InfoPageId == infoId));
    this.infos = filteredResults;
  }

See StackBlitz.

Note that the output only shows one of the tags, because that's how you wrote your output example (it only outputs the first row containing a given PageInfoId). If you want the filtered objects to contain all matched TagIds, I'll have to change it a little.

I left them as is, but I highly suggest that you rename your vars to comply with OOP naming conventions - don't name vars in PascalCase (starting with uppercase), since the style is reserved for classes. Prefer using lower camelCase for properties.

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

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.