Я пытаюсь отсортировать массив строк по числовому значению в Angular2 с помощью пользовательского канала ( я не писал этот канал ). Вот эта труба:

import { Pipe, PipeTransform } from "@angular/core";

@Pipe( { name: 'numericalSort' } )

export class NumericalSortPipe implements PipeTransform {
transform( array: Array<any>, orderField: string, orderType: boolean ): Array<string> {
    array.sort( ( a: any, b: any ) => {
        let ae = a[ orderField ];
        let be = b[ orderField ];
        if ( ae == undefined && be == undefined ) return 0;
        if ( ae == undefined && be != undefined ) return orderType ? 1 : -1;
        if ( ae != undefined && be == undefined ) return orderType ? -1 : 1;
        if ( ae == be ) return 0;
        return orderType ? (ae.toString().toLowerCase() > be.toString().toLowerCase() ? -1 : 1) : (be.toString().toLowerCase() > ae.toString().toLowerCase() ? -1 : 1);
    } );
    return array;
  }
}

Здесь объект. Мне нужно иметь возможность отсортировать по количеству по " метка ".

{
  "id" : "12345678",
  "accountId" : "123456789",
  "label" : "906",
  "fullAddress" : {
    "zip" : "12345"
  }
}

Вот пример HTML:

<div *ngFor="let place of places | numericalSort: 'label'">
  <h3>
    {{place.label}}
  </h3>
  ...
</div>

Я могу сортировать по умолчанию по алфавиту. Как я могу отсортировать по числовому значению?

1
bk819284 19 Сен 2017 в 20:41

3 ответа

Лучший ответ

Я бы добавил новый параметр в канал, который будет указывать реальный тип поля. Таким образом, канал сможет преобразовывать строковые поля элементов в вашем массиве в реальные типы:

export class NumericalSortPipe implements PipeTransform {
    transform(array: Array<any>, orderField: string, orderType: boolean, dataType: string): Array<string> {
        array.sort((a: any, b: any) => {
            let ae = a[orderField];
            let be = b[orderField];
            if (ae === undefined && be === undefined) return 0;
            if (ae === undefined && be !== undefined) return orderType ? 1 : -1;
            if (ae !== undefined && be === undefined) return orderType ? -1 : 1;
            if (ae === be) return 0;
            switch (dataType) {
                case "number":
                    ae = parseFloat(ae);
                    be = parseFloat(be);
                    break;
                case "string":
                    ae = ae.toString().toLowerCase();
                    be = be.toString().toLowerCase();
                    break;

                default:
                    break;
            }
            return orderType ? (ae > be ? -1 : 1) : (be > ae ? -1 : 1);
        });
        return array;
    }
}

И использование:

<div *ngFor="let place of places | numericalSort: 'label':false:'number'">
    <h3>
        {{place.label}}
    </h3>
    {{place.id}}
</div>

Смотрите plunk.

1
Gosha_Fighten 20 Сен 2017 в 19:16

Вы можете использовать lodash для сортировки.

var myArray = [ 3, 4, 2, 9, 4, 2 ];

_.sortBy(myArray);
// → [ 2, 2, 3, 4, 4, 9 ]

_(myArray).sortBy().take(3).value();
// → [ 2, 2, 3 ]
0
Praneeth Reddy 19 Сен 2017 в 17:43

Вот труба для заказа сначала числовых, а затем букв:

@Pipe({name: "orderBy", pure: false})
export class OrderByPipe implements PipeTransform {
  transform(array: Array<any>) {
    return array.sort((a, b) => {
        const [stringA, numberA] = this.order(a);
        const [stringB, numberB] = this.order(b);
        const comparison = stringA.localeCompare(stringB);
        return comparison === 0 ? Number(numberA) - Number(numberB) : comparison;
  })
  }

   order (item) {
      const [, stringPart = '', numberPart = 0] = /(^[a-zA-Z]*)(\d*)$/.exec(item) || [];
  return [stringPart, numberPart];
  }
}

DEMO

0
Vega 20 Сен 2017 в 14:39