TypeScript сортування масиву


154

Я намагався з'ясувати дуже дивну проблему, з якою я зіткнувся з машинописом. Він ставився до вбудованого булевого виразу як до типу першого значення, а не до повного виразу.

Тож якщо ви спробуєте щось просте, наприклад:

var numericArray:Array<number> = [2,3,4,1,5,8,11];

var sorrtedArray:Array<number> = numericArray.sort((n1,n2)=> n1 > n2);

Спробуй це

Ви отримаєте помилку в своєму методі сортування, кажучи, що параметри не відповідають жодній підпису цілі виклику, оскільки ваш результат є числовим, а не булевим. Я думаю, мені щось не вистачає, тому що я майже впевнений, що n1> n2 - булева заява.

Відповіді:


180

Помилка повністю коректна.

Як він намагається вам сказати, .sort()приймає функцію, яка повертає число, а не булева.

Ви повинні повернути мінус, якщо перший елемент менший; позитивний, якщо він більший, або нуль, якщо вони рівні.


56
Ось чому ми використовуємо TypeScript! :-)
— Стівен Чун

226

Числа

При сортуванні чисел можна використовувати компактне порівняння:

var numericArray: number[] = [2, 3, 4, 1, 5, 8, 11];

var sortedArray: number[] = numericArray.sort((n1,n2) => n1 - n2);

тобто, -а не <.

Інші типи

Якщо ви порівнюєте щось інше, вам потрібно буде перетворити порівняння в число.

var stringArray: string[] = ['AB', 'Z', 'A', 'AC'];

var sortedArray: string[] = stringArray.sort((n1,n2) => {
    if (n1 > n2) {
        return 1;
    }

    if (n1 < n2) {
        return -1;
    }

    return 0;
});

Об'єкти

Для об'єктів ви можете сортувати на основі властивості, майте на увазі вищенаведену інформацію про можливість коротких типів номерів. Наведений нижче приклад працює незалежно від типу.

var objectArray: { age: number; }[] = [{ age: 10}, { age: 1 }, {age: 5}];

var sortedArray: { age: number; }[] = objectArray.sort((n1,n2) => {
    if (n1.age > n2.age) {
        return 1;
    }

    if (n1.age < n2.age) {
        return -1;
    }

    return 0;
});

Чи може хтось пояснити, чому для менш тестового тесту "Roy@my.net" повертає істину менше, ніж "bob@my.net"? наприклад: нехай myTest = ('Roy@my.net' <'bob@my.net'); // повертає справжнє для мене ... :(
— Wallace Howery

1
у другому випадку ви можете використовувати localeCompare () для порівняння рядків у поточному локалі, який повертає число
— neural5torm

Поясніть, будь ласка, як (n1,n2)=>n1-n2вираження буде виконуватися чи працювати .. ??
— Рахул Чаудхарі

1
@RahulChaudhari в прикладі числа - це функція, яка приймає числа, n1і n2в межах функції вона повертається n1-n2, яка буде або додатним числом, нулем, або від’ємним числом. Це повідомляє операцію сортування, чи потрібно перемикати елементи чи ні, тим самим дозволяючи сортувати.
— Фентон

його може бути можливий фільтр з різною proprty
— Ервінд

24

Чудова відповідь Соні. Хочеться додати, що якщо у вас є масив об’єктів і ви хочете сортувати за клавішами, то його майже однакові, це приклад одного, який можна сортувати за датою (номером) або заголовком (рядком):

    if (sortBy === 'date') {
        return n1.date - n2.date
    } else {
        if (n1.title > n2.title) {
           return 1;
        }
        if (n1.title < n2.title) {
            return -1;
        }
        return 0;
    }

Можна також зробити значення всередині як змінні n1 [поле] проти n2 [поле], якщо його більш динамічним, просто збережіть різницю між рядками та числами.


Коментувати відповіді слід за допомогою функції коментарів.
— Ніккер

6
@Nicktar Це, ймовірно, розміщено як відповідь на форматування. Але це ніяк не шкодить
— Wouter Vanherck,

11
let numericArray: number[] = [2, 3, 4, 1, 5, 8, 11];

let sortFn = (n1 , n2) => number { return n1 - n2; }

const sortedArray: number[] = numericArray.sort(sortFn);

Сортувати за деяким полем:

let arr:{key:number}[] = [{key : 2}, {key : 3}, {key : 4}, {key : 1}, {key : 5}, {key : 8}, {key : 11}];

let sortFn2 = (obj1 , obj2) => {key:number} { return obj1.key - obj2.key; }

const sortedArray2:{key:number}[] = arr.sort(sortFn2);

1
n1 - n2 від'ємна, коли n1 <n2, додатна, коли n1> n2 і 0, коли n1 == n2
— Себастьян Стормак

2
Дякую! Я змінив це для цього: myArray.sort ((a, b): number => {return a.NumberProp - b.NumberProp;});
— Lrodriguez84

10

Сортувати змішаний масив (алфавіти та числа)

function naturalCompare(a, b) {
   var ax = [], bx = [];

   a.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) });
   b.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) });

   while (ax.length && bx.length) {
     var an = ax.shift();
     var bn = bx.shift();
     var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]);
     if (nn) return nn;
   }

   return ax.length - bx.length;
}

let builds = [ 
    { id: 1, name: 'Build 91'}, 
    { id: 2, name: 'Build 32' }, 
    { id: 3, name: 'Build 13' }, 
    { id: 4, name: 'Build 24' },
    { id: 5, name: 'Build 5' },
    { id: 6, name: 'Build 56' }
]

let sortedBuilds = builds.sort((n1, n2) => {
  return naturalCompare(n1.name, n2.name)
})

console.log('Sorted by name property')
console.log(sortedBuilds)


Дуже дякую :)
— Стів


0

function naturalCompare(a, b) {
   var ax = [], bx = [];

   a.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) });
   b.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) });

   while (ax.length && bx.length) {
     var an = ax.shift();
     var bn = bx.shift();
     var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]);
     if (nn) return nn;
   }

   return ax.length - bx.length;
}

let builds = [ 
    { id: 1, name: 'Build 91'}, 
    { id: 2, name: 'Build 32' }, 
    { id: 3, name: 'Build 13' }, 
    { id: 4, name: 'Build 24' },
    { id: 5, name: 'Build 5' },
    { id: 6, name: 'Build 56' }
]

let sortedBuilds = builds.sort((n1, n2) => {
  return naturalCompare(n1.name, n2.name)
})

console.log('Sorted by name property')
console.log(sortedBuilds)


Привіт, Ласкаво просимо до stackoverflow, stackoverflow.com/help/how-to-answer, будь ласка, прочитайте цю документацію та надайте деякий опис, що потрібно зробити.
— Prateik Darji

0

Я написав це сьогодні, намагаючись відтворити _.sortByв TypeScript, і думав, що залишу його для всіх, хто потребує.

// ** Credits for getKeyValue at the bottom **
export const getKeyValue = <T extends {}, U extends keyof T>(key: U) => (obj: T) => obj[key] 

export const sortBy = <T extends {}>(index: string, list: T[]): T[] => {
    return list.sort((a, b): number => {
        const _a = getKeyValue<keyof T, T>(index)(a)
        const _b = getKeyValue<keyof T, T>(index)(b)
        if (_a < _b) return -1
        if (_a > _b) return 1
        return 0
    })
}

Використання:

Він очікує масив загального типу T, отже, і команда для <T extends {}>, а також введення параметра і типу повернення функції зT[]

const x = [{ label: 'anything' }, { label: 'goes'}]
const sorted = sortBy('label', x)

** getByKeyfn тут знайдено

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.