在Angular2 * ngFor迭代中,如何仅输出数组中的唯一值?

时间:2017-01-26 05:30:09

标签: angular

它有内置管道吗?

data = [
  {id: 5, name: 'Roger'},
  {id: 5, name: 'Mark'},
  {id: 5, name: 'Zach'},
  {id: 5, name: 'Mark'},
  {id: 5, name: 'Roger'},
];

<ul>
  <li *ngFor="let datum of data">
    {{datum.name}}
  </li>
</ul>

Output

  • 罗杰
  • 标记
  • 扎克
  • 标记
  • 罗杰

Desired Output

  • 罗杰
  • 标记
  • 扎克

2 个答案:

答案 0 :(得分:11)

您可以创建自己的管道。

import { Pipe, PipeTransform } from '@angular/core';
import * as _ from 'lodash'; 

@Pipe({
  name: 'unique',
  pure: false
})

export class UniquePipe implements PipeTransform {
    transform(value: any): any{
        if(value!== undefined && value!== null){
            return _.uniqBy(value, 'name');
        }
        return value;
    }
}

您需要在组件中添加UniquePipe,然后在HTML文件中添加管道。

<ul>
  <li *ngFor="let datum of data | unique">
    {{datum.name}}
  </li>
</ul>

答案 1 :(得分:6)

这有点旧,但我想为未来找到这个的人添加一个答案。

接受的答案建议使用实现目标的管道,但在这种情况下不是推荐的方法。这里我们讨论的是列表过滤器,一个非常具体的复制过滤器。最糟糕的情况是此操作上的大O可能接近n ^ 2或者相当大的内存密集(取决于您的方法),并且管道操作在每个更改检测周期执行,并且非常频繁地更改Angular触发器中的检测。如果此列表非常长,或者如果您对此进行了练习,那么您的应用程序将停止运行并且您将遇到明显的性能问题。

Angular 1实际上包含了一个“过滤器”管道,但团队选择在角度2中摆脱它,因为过滤管道的滥用导致人们将角色1归咎于这种不良做法导致的性能问题。管道用于非常小的数据转换,例如格式化数字或字符串。

你应该这样做的方法是在代码中过滤你的列表,并构建逻辑以自己触发过滤(例如当你的列表实际发生变化时),而不是依靠变化检测来为你做。在这种情况下很难确切地说明如何执行此操作,因为它非常特定于用例,如果您希望应用程序运行良好,则应该如此。一个相当通用的例子是如果这个列表来自一个可观察的流(应该如此),那么只需在map运算符中执行此操作并使用async,如下所示:

dataSource = Observable.of(data); //this is just for example, the actual data source should be an http call or some service layer subject that you can actually update / trigger    
uniqueData$ = this.dataSource.map(data => _.uniqBy(data, 'name'));

<ul>
  <li *ngFor="let datum of uniqueData$ | async">
    {{datum.name}}
  </li>
</ul>

这里的优点是过滤操作仅在可观察流触发时触发,因此您可以非常高地控制何时进行过滤,并且仍然非常容易推理并且非常“确定正确”#