Как отсортировать массив объектов в js

Мне нужно отсортировать массив объектов в js по массиву имен свойств, который передается в функцию. Вот к примеру

function sorting(obj, propName){

}


initial = [
    {a : 1, b : "abc"},
    {a : 2, b : "def"},
]

sorting(initial, ["a"]);       //1
sorting(initial, ["b", "a"]);  //2

В первом случае объекты в массиве initial должны быть отсортированы по свойству 'a', а во втором первично по свойству 'b' и вторично по свойству 'a'(т.е лексеграфически). Сортировка должна идти по возрастанию и быть устойчивой. Как это сдедлать?


Ответы (1 шт):

Автор решения: wololo

Можно написать компаратор, которые сперва сравнивает два объекта по нулевому свойству из массива propName, если данное свойство одинаково у двух объектов, то по следующему свойству из массива propName, и т.д.

Так как спецификация языка не требует, чтобы метод sort использовал устойчивую сортировку (1), то необходимо самостоятельно позаботиться об обеспечении устойчивости сортировки. Например, можно сортировать не исходный массив, а массив пар [элемент_исходного_массива, индекс_в_исходном_массиве]. Если два объекта равны по всем интересующим нас свойствам, то сравниваем индексы объектов.

function sorting(objArr, propName)
{
    for (let i = 0; i < objArr.length; ++i)
        objArr[i] = [objArr[i], i];
    
    function comparator(a, b)
    {
        for (let prop of propName)
        {
            if (a[0][prop] < b[0][prop])
                return -1;
            else if (a[0][prop] > b[0][prop])
                return 1;
        }
        return a[1] - b[1];
    }

    objArr.sort(comparator);

    for (let i = 0; i < objArr.length; ++i)
        objArr[i] = objArr[i][0];
}

let initial = [
    {a : 2, b : "def", c: 7},
    {a : 3, b : "def", c: 6},
    {a : 1, b : "def", c: 5},
    {a : 1, b : "def", c: 4},
    
    {a : 3, b : "abc", c: 3},
    {a : 2, b : "abe", c: 2},
    {a : 2, b : "abd", c: 1},
    {a : 2, b : "abc", c: 0},
];

console.log(1);
sorting(initial, ["a"]);       //1
for (let obj of initial)
    console.log(JSON.stringify(obj));

console.log(2);
sorting(initial, ["b", "a"]);  //2
for (let obj of initial)
    console.log(JSON.stringify(obj));


(1):

В ECMA-262, 9th edition, June 2018 говорится следующее (Array.prototype.sort):

The elements of this array are sorted. The sort is not necessarily stable (that is, elements that compare equal do not necessarily remain in their original order).

Но начиная с ECMA-262, 10th edition, June 2019 сортировка должна быть стабильной (Array.prototype.sort):

The elements of this array are sorted. The sort must be stable (that is, elements that compare equal must remain in their original order).

→ Ссылка