在Angular2中对对象数组进行排序

Posted

技术标签:

【中文标题】在Angular2中对对象数组进行排序【英文标题】:Sort an array of objects in Angular2 【发布时间】:2017-04-27 11:44:06 【问题描述】:

我在 Angular2 中对对象数组进行排序时遇到问题。

对象看起来像:

[
  
    "name": "t10",
    "ts": 1476778297100,
    "value": "32.339264",
    "xid": "DP_049908"
  ,
  
    "name": "t17",
    "ts": 1476778341100,
    "value": "true",
    "xid": "DP_693259"
  ,
  
    "name": "t16",
    "ts": 1476778341100,
    "value": "true",
    "xid": "DP_891890"
  
]

并且被存储在values 变量中。

我只想让*ngFor 循环按name 属性对其进行排序。

<table *ngIf="values.length">
    <tr *ngFor="let elem of values">
      <td> elem.name </td>
      <td> elem.ts </td>
      <td> elem.value </td>
    </tr>
</table>

尝试使用管道进行此操作,但惨遭失败。 任何帮助表示赞赏。

Plunker 链接:https://plnkr.co/edit/e9laTBnqJKb8VzhHEBmn?p=preview

编辑

我的烟斗:

import Component, Inject, OnInit, Pipe, PipeTransform from '@angular/core';

@Component(
  selector: 'watchlist',
  templateUrl: './watchlist.component.html',
  styleUrls: ['./watchlist.component.css'],
  pipes: [ ArraySortPipe ]
)
@Pipe(
  name: "sort"
)

export class ArraySortPipe implements PipeTransform 
  transform(array: Array<string>, args: string): Array<string> 
    array.sort((a: any, b: any) => 
      if (a < b) 
        return -1;
       else if (a > b) 
        return 1;
       else 
        return 0;
      
    );
    return array;
  

只需将 pipe 名称放入 html 文件:

<tr *ngFor="let elem of values | sort">

【问题讨论】:

到目前为止您尝试了什么?你可以在这里添加你尝试写的管道吗? @toskv 我制作的管道无法正常工作,但我会尽快在编辑中添加它。 谢谢。展示你的工作对人们能够帮助你很重要。 :) 由于您是新手,如果您还没有阅读指南,可能值得一读。 ***.com/help/how-to-ask 也许您应该尝试对 name 属性进行排序。在管道中的箭头函数中 do 和 a.name 【参考方案1】:

这适用于任何此类用例。

import  Pipe, PipeTransform  from '@angular/core';

@Pipe(
  name: 'sortBy'
)
export class SortByPipe implements PipeTransform 
  transform(arr: Array<any>, prop: any, reverse: boolean = false): any 
    if (arr === undefined) return
    const m = reverse ? -1 : 1
    return arr.sort((a: any, b: any): number => 
      const x = a[prop]
      const y = b[prop]
      return (x === y) ? 0 : (x < y) ? -1*m : 1*m
    )
  

用法:-&lt;div *ngFor="let item of list | sortBy: 'isDir': true"&gt;

更新 请参考Bo's 的回答,因为不建议在管道中进行过滤和排序。

【讨论】:

结帐angular.io/guide/pipes#no-filter-pipe在这里排序不是一个好习惯。 Bo Vandersteene ,更新了我的答案。您可以取消您的反对票。谢谢【参考方案2】:

试试这个

从 A 到字母的结尾排序:

this.suppliers.sort((a,b)=>a.SupplierName.localeCompare(b.SupplierName));

Z=>A(倒序)

this.suppliers.sort((a,b)=>b.SupplierName.localeCompare(a.SupplierName));

【讨论】:

最简单的有效答案,不值得反对。 不反对投票,但对代码的一些解释会有所帮助。 A=&gt;Z 这是箭头函数的简写吗?也许澄清一下“localeCompare”是一种包含特定语言字符的内置方法? 当放置在订阅所在的构造函数中时,这对我有用: this.foo.getBar().subscribe(x => this.thing = x; this.thing= (this.thing || []).sort((a: Thing, b: Thing) => a.name.localeCompare(b.name)); );我看到 a=>z 是文本。在那里完全困惑了一段时间:) @RinandLen 'localeCompare' 根据顺序返回负值、正值或零值。然后 sort 函数使用它对其进行排序。 developer.mozilla.org/en-US/docs/Web/javascript/Reference/…developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…【参考方案3】:

很简单,例如如果你有这个数组对象:

 cars = ["Dodge", "Fiat", "Audi", "Volvo", "BMW", "Ford"];

如果您想让对象在 HTML 前面排序,请使用:

 <li ng-repeat="x in cars | orderBy">x</li>

默认情况下,字符串按字母排序,数字按数字排序。

如果你有这个带键的数组:

customers = [
"name" : "Bottom-Dollar Marketse" ,"city" : "Tsawassen",
"name" : "Alfreds Futterkiste", "city" : "Berlin",
"name" : "Bon app", "city" : "Marseille",
"name" : "Cactus Comidas para llevar", "city" : "Buenos Aires",
"name" : "Bolido Comidas preparadas", "city" : "Madrid",
"name" : "Around the Horn", "city" : "London",
"name" : "B's Beverages", "city" : "London"
];

用途:

按“城市”DESC 顺序对数组进行排序:

<li ng-repeat="x in customers | orderBy : '-city'">x.name + ", " + x.city</li>

按“城市”对数组进行排序:

<li ng-repeat="x in customers | orderBy : 'city'">x.name + ", " + x.city</li>

【讨论】:

显然 ng-repeat 适用于旧版本的 angularJs,最近使用 * ngFor 在 Angular 1.x 或 Angular 2+ 中仍然不是一个好习惯【参考方案4】:

Angular 仍然建议不要像在 angularJs 中那样使用管道进行排序和过滤。

它会减慢您的应用程序,出现一些性能问题。在将组件传递给模板之前,最好在组件中提供排序。

原因在https://angular.io/guide/pipes#no-filter-pipe有解释

如果你使用一个漂亮的结构化组件布局,你甚至可以在 te setter 上做到这一点:

 @Input()
  set users(users: Array<User>) 
    this.usersResult = (users || []).sort((a: User, b: User) => a.name < b.name ? -1 : 1)
  

【讨论】:

什么是“userResult”(除了你编的一个变量)?它在上面的代码中显然是未定义的,没有在其他地方声明,并且将其更改为我的组件中的任何现有值都会产生“超出最大调用堆栈大小”。 用户结果将是您的排序数组的结果。您只需将其重新分配给其他东西【参考方案5】:

您的管道需要字符串,但它获取对象,您应该调整它:

export class ArraySortPipe implements PipeTransform 
  transform(array: Array<any>): Array<string> 
    array.sort((a: any, b: any) => 
      if (a.name < b.name) 
        return -1;
       else if (a.name > b.name) 
        return 1;
       else 
        return 0;
      
    );
    return array;
  

【讨论】:

不幸的是它不起作用。将您的解决方案包含到我的项目中后,我收到一个错误:Argument of type ' selector: string; template: any; styles: any[]; pipes: typeof ArraySortPipe[]; ' is not assignable to parameter of type 'Component'. Object literal may only specify known properties, and 'pipes' does not exist in type 'Component'. 可能是签名的原因,更新为接受Array,试试看 这里几乎是整个component.ts 文件和出现的错误:jsfiddle.net/ra7szrLn/1 即使我已经改变了你所说的一切,它仍然有问题。 该错误是由于 jsfiddle 上的编译问题还是我错过了什么?为什么不分叉并修复原来的 plnkr? 这个错误来自 webpack 在编译应用程序时。我现在使用了 jsfiddle,因为我在 plunker 上发布了我的代码的最小且非常简化的版本,没有 http 请求。如果你愿意,我可以编辑原来的 plunker,我的朋友。【参考方案6】:

虽然您可以使用管道解决此问题,但您必须问问自己,管道的可重用性是否对您在特定项目中有用。以后是否经常需要在其他数组或其他组件上按“name”键对对象进行排序?这些数据是否会经常发生变化,并且以难以在组件中简单排序的方式发生变化?您是否需要根据视图或输入的任何更改对数组进行排序?

我创建了一个已编辑的 plunker,其中数组在组件的构造函数中排序,但没有理由不能将此功能移出到它自己的方法(例如 sortValuesArray)中以便在必要时重新使用。

constructor() 
  this.values.sort((a, b) => 
    if (a.name < b.name) return -1;
    else if (a.name > b.name) return 1;
    else return 0;
  );

Edited Plunker

【讨论】:

谢谢,但这不是我要找的。​​span> 在某些情况下,代码可能更简单,如constructor() this.values.sort(function(a, b)return a.ts - b.ts); constructor() this.values.sort((a, b) =&gt; return a.ts - b.ts); 这种方法的论据在angular.io/guide/pipes 提出:“Angular 不提供这样的管道,因为它们性能很差......过滤,尤其是排序是昂贵的操作。用户体验可能会严重降低当 Angular 每秒多次调用这些管道方法时,即使是中等大小的列表。filter 和 orderBy 在 AngularJS 应用程序中经常被滥用,导致抱怨 Angular 本身很慢...... Angular 团队和许多有经验的 Angular 开发人员强烈建议移动过滤并将逻辑排序到组件本身。”

以上是关于在Angular2中对对象数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中对对象数组进行排序?

如何在Vue中对对象数组进行排序和过滤

在 Redux reducer 中对对象数组进行排序

如何在javascript中对嵌套的对象数组进行排序?

如何在 Swift 中对对象数组进行排序?

如何根据用户输入在 C# 中对对象数组进行排序?