首页 > 解决方案 > 如何过滤数组并添加到新数组

问题描述

我有一个名为“infos”的对象数组,在这个对象数组中我有一个名为 TagId 的元素。我有另一个名为“TagIds”的数组,它在任何给定时间都包含 0-3 个 ID。我想遍历我的“infos”数组中的每个对象,如果有匹配项,则将该对象添加到我的“filteredResults”数组中。

现在我通过以下代码实现了这一点:

  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;
  }

现在的问题是我的对象数组“信息”包含重复数据,例如:

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"}
]

但是,您可以看到 TagId 是不同的。

我希望能够遍历我的“infos”数组,并且只将对象添加到我的“filteredResults”数组中,但也只在“Tagids”数组中存在具有相同“InfoPageId”的每个对象的 TagId 时添加该对象. 例如,如果“InfoPageId”为 8 的对象的 TagId 为 12 和 15,并且“TagIds”数组的值为 12 和 15,则将对象添加到“filteredResults”数组中,但如果对象仅包含12 但“TagIds”数组的值 12 和 15 不相加。

所需输出的示例;

输入:

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"}
]

输出:

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

希望你们能明白这一点。它很难解释。

标签: javascripthtmlarraysangularfilter

解决方案


试试这个:

  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;
  }

请参阅StackBlitz

请注意,输出仅显示一个标签,因为这就是您编写输出示例的方式(它仅输出包含给定 的第一行PageInfoId)。如果您希望过滤后的对象包含所有match TagIds,我将不得不对其进行一些更改。

我将它们保持原样,但我强烈建议您重命名变量以符合OOP 命名约定- 不要以 PascalCase 命名变量(以大写开头),因为该样式是为类保留的。更喜欢使用较低的驼峰命名法作为属性。


推荐阅读