角键值管道排序属性/按顺序迭代

时间:2018-10-13 14:26:49

标签: angular angular-pipe

当使用Angular keyvalue管道迭代对象的属性时,如下所示:

<div *ngFor="let item of object | keyvalue">
  {{item.key}}:{{item.value}}
</div>

我遇到了一个问题,即属性没有按预期的顺序进行迭代。此评论表明我不是唯一遇到此问题的人:

How to loop over object properties with ngFor in Angular

有人可以建议使用键值管道时由什么决定迭代顺序以及如何强制执行特定的迭代顺序吗?我理想的迭代顺序是添加属性的顺序。

谢谢

10 个答案:

答案 0 :(得分:16)

根据角度documentationkeyvalue管道默认情况下按key顺序对项目进行排序。您可以提供比较器功能来更改排序顺序,但是它仅考虑keyvalue属性,而不考虑输入顺序。

例如,以下比较器函数分别按增加值顺序和反向键顺序对项目进行排序:

valueAscOrder = (a: KeyValue<number,string>, b: KeyValue<number,string>): number => {
  return a.value.localeCompare(b.value);
}

keyDescOrder = (a: KeyValue<number,string>, b: KeyValue<number,string>): number => {
  return a.key > b.key ? -1 : (b.key > a.key ? 1 : 0);
}

应用于keyvalue管道时:

<div *ngFor="let item of object | keyvalue: valueAscOrder">
  {{item.key}} : {{item.value}}
</div>

<div *ngFor="let item of object | keyvalue: keyDescOrder">
  {{item.key}} : {{item.value}}
</div>

有关演示,请参见this stackblitz

答案 1 :(得分:13)

put()

直接写入,您将获得与json中相同的数据

for i in range(len(df_cleaned)):
    outputFile = df_cleaned[i].to_csv(r'C:\...\Data Docs\TrainData\{}.csv'.format(name))
print('Saving of files as csv is complete.')

答案 2 :(得分:4)

尝试以下代码:

<div *ngFor="let item of object | keyvalue: 0">
  {{item.key}} : {{item.value}}
</div>

答案 3 :(得分:3)

这与已接受的答案相同,但是它具有更复杂的对象,因此可以帮助某人如何通过自定义索引字段进行排序并使用keyval管道。

在角度分量中:

myObject = {
    "key1": { val:"whateverVal1", code:"whateverCode1", index: 1},
    "key2": { val:"whateverVal2", code:"whateverCode2", index: 0},
    "key3": { val:"whateverVal3", code:"whateverCode3", index: 2}
}

组件中的排序功能:

indexOrderAsc = (akv: KeyValue<string, any>, bkv: KeyValue<string, any>): number => {
        const a = akv.value.index;
        const b = bkv.value.index;

        return a > b ? 1 : (b > a ? -1 : 0);
    };

在模板中:

<div *ngFor="let x of myObject | keyvalue:indexOrderAsc">
    ...
</div>

答案 4 :(得分:3)

我更喜欢通过在管道中扩展默认的keyvalue行为。然后,我在模板中使用管道而不是keyvalue

import {Pipe} from '@angular/core';
import {KeyValuePipe} from '@angular/common';

const keepOrder = (a, b) => a;

// This pipe uses the angular keyvalue pipe. but doesn't change order.
@Pipe({
  name: 'defaultOrderKeyvalue'
})
export class DefaultOrderKeyvaluePipe extends KeyValuePipe {

  public transform(value, compareFn = keepOrder) {
    return super.transform(value, compareFn);
  }

}

答案 5 :(得分:2)

是的,默认情况下,键值对以升序对数据进行排序。

要使其保持未排序状态,请修改为:

keyvalue: 0
  

最终代码:

<div *ngFor="let item of object | keyvalue:0">
  {{item.key}}:{{item.value}}
</div>
  

但是对于角度7或更高的角度,您需要放置一个空函数来保持   数据未排序。

<div *ngFor="let item of object | keyvalue: unsorted">
      {{item.key}}:{{item.value}}
    </div>

在您的.ts文件中放一个空函数。

  unsorted() { }

希望有帮助。

答案 6 :(得分:1)

是的,Object属性是随机迭代的,因为它不会作为array存储在内存中。但是,您可以按属性排序。

如果要按插入位置进行迭代,则需要创建一个额外的属性,例如index,并设置timestamp并按index进行排序。

下面是可用于控制排序和迭代的管道

管道

import {Pipe, PipeTransform} from 'angular2/core';

@Pipe({name: 'values'})
export class ValuesPipe implements PipeTransform {
    transform(value: any, args?: any[]): Object[] {
        let keyArr: any[] = Object.keys(value),
            dataArr = [],
            keyName = args[0];

        keyArr.forEach((key: any) => {
            value[key][keyName] = key;
            dataArr.push(value[key])
        });

        if(args[1]) {
            dataArr.sort((a: Object, b: Object): number => {
                return a[keyName] > b[keyName] ? 1 : -1;
            });
        }

        return dataArr;
    }
}

用法

<div *ngFor='#item in object | values:"keyName":true'>...</div>

答案 7 :(得分:1)

要保持对象顺序,可以使用

wbs = {
"z": 123,
"y": 456,
"x": 789,
"w": 0#*
}

假设您有

w 0#*
x 789
y 456
z 123

如果您使用键值,则会按键获得字母顺序

<ion-item *ngFor="let w of wbs | keyvalue: keepOrder">
    <ion-label>{{ w.key }}</ion-label>
    <ion-label>{{ w.value }}</ion-label>
</ion-item>

应用:keepOrder保持对象顺序

const express = require('express');
const next = require('next');

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });

const handle = app.getRequestHandler();

app
  .prepare()
  .then(() => {

    const server = express();

    server.use((req, res, next) => {
      const hostname = req.hostname === 'www.app.domain.com' ? 'app.domain.com' : req.hostname;

      if (req.headers['x-forwarded-proto'] === 'http' || req.hostname === 'www.app.domain.com') {
        res.redirect(301, `https://${hostname}${req.url}`);
        return;
      }

      res.setHeader('strict-transport-security', 'max-age=31536000; includeSubDomains; preload');
      next();
    });

    server.get('*', (req, res) => handle(req, res));

    server.listen(
      4242,
      error => {
        if (error) throw error;
        console.error('Listening on port 4242');
      }
    );

  })
  .catch(error => {
    console.error(error);
    process.exit(1);
  });

答案 8 :(得分:1)

制作管道以将默认设置为无序:

// src/app/pipes/new-key-value.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { KeyValuePipe } from '@angular/common';
import { KeyValueDiffers } from '@angular/core';
const unordered = (a,b)=>0

@Pipe({
  name: 'newkeyvalue'
})

// This pipe uses the angular keyvalue pipe. but defaults to unordered.
export class NewKeyValuePipe implements PipeTransform {

  constructor(public differs: KeyValueDiffers){};
  public transform (value, compareFn = unordered){
    let pipe =  new KeyValuePipe(this.differs);
    return pipe.transform(value, compareFn)
  }
}

链接:

Can I call an Angular2 pipe from a pipe?

https://github.com/angular/angular/blob/8.2.14/packages/common/src/pipes/keyvalue_pipe.ts#L25-L89

模板用法:

// src/app/some-component/some-component.html
<div *ngFor="let x of myObject | newkeyvalue>
</div>

在module.ts中注册

// src/app/app.module.ts
import { NewKeyValuePipe } from '@/pipes/new-key-value.pipe.ts'
...
@NgModule({
  declarations: [
    ...
    NewKeyValuePipe,
    ...
  ]
...
})

答案 9 :(得分:1)

我认为这是一种更清洁的解决方案。取消注释需要给出正确顺序的return语句:

interface KeyValue<K, V> {
  key: K,
  value: V
}

// Order by descending property key
  keyOrder = (aA: KeyValue<string,any>, bB: KeyValue<string,any>): number => {
    const a = aA.value.index;
    const b = bB.value.index;
    //return a > b ? 1 : (b > a ? -1 : 0); // ASCENDING
    return a > b ? -1 : (b > a ? 1 : 0); // DESCENDING
  }

使用案例

<div *ngFor="let x of y | keyvalue: keyOrder;">
   {{ x.key  }} indexes: {{ x.value.index }}
</div>