Javascript сортировать массив по двум полям - PullRequest
59 голосов
/ 25 мая 2011
grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    var aLow = a.glow;
    var bLow = b.glow;
    console.log(aLow + " | " + bLow);      
    return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;
});

Таким образом, приведенный выше код сортирует массив по gsize - от наименьшего к наибольшему.Работает хорошо.Но если размер gsize тот же, я бы хотел, чтобы он сортировал по свету.

Спасибо.

Ответы [ 13 ]

104 голосов
/ 18 июня 2014
grouperArray.sort(function (a, b) {   
    return a.gsize - b.gsize || a.glow - b.glow;
});

укороченная версия

76 голосов
/ 25 мая 2011
grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    var aLow = a.glow;
    var bLow = b.glow;
    console.log(aLow + " | " + bLow);

    if(aSize == bSize)
    {
        return (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0;
    }
    else
    {
        return (aSize < bSize) ? -1 : 1;
    }
});
11 голосов
/ 27 марта 2014

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

Эта функция генерирует методы сортировки динамически. просто укажите каждое сортируемое имя дочернего свойства с добавлением +/- для обозначения возрастающего или убывающего порядка. Супер многоразовое использование, и ему не нужно ничего знать о структуре данных, которые вы собрали. Может быть доказано идиотом - но не кажется необходимым.

function getSortMethod(){
    var _args = Array.prototype.slice.call(arguments);
    return function(a, b){
        for(var x in _args){
            var ax = a[_args[x].substring(1)];
            var bx = b[_args[x].substring(1)];
            var cx;

            ax = typeof ax == "string" ? ax.toLowerCase() : ax / 1;
            bx = typeof bx == "string" ? bx.toLowerCase() : bx / 1;

            if(_args[x].substring(0,1) == "-"){cx = ax; ax = bx; bx = cx;}
            if(ax != bx){return ax < bx ? -1 : 1;}
        }
    }
}

пример использования:

items.sort (getSortMethod ('- цена', '+ приоритет', '+ имя'));

это отсортировало бы items с самым низким price первым, с галстуками, идущими к предмету с самым высоким priority дальнейшие связи нарушены предметом name

где items - это массив вроде:

var items = [
    { name: "z - test item", price: "99.99", priority: 0, reviews: 309, rating: 2 },
    { name: "z - test item", price: "1.99", priority: 0, reviews: 11, rating: 0.5 },
    { name: "y - test item", price: "99.99", priority: 1, reviews: 99, rating: 1 },
    { name: "y - test item", price: "0", priority: 1, reviews: 394, rating: 3.5 },
    { name: "x - test item", price: "0", priority: 2, reviews: 249, rating: 0.5 } ...
];

живое демо: http://gregtaff.com/misc/multi_field_sort/

РЕДАКТИРОВАТЬ: Исправлена ​​проблема с Chrome.

10 голосов
/ 28 сентября 2017
grouperArray.sort((a, b) => a.gsize - b.gsize || a.glow - b.glow);

Еще более короткая версия с использованием синтаксиса стрелок!

6 голосов
/ 25 мая 2011

Я ожидаю, что троичный оператор ((aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;) вас смутил.Вы должны проверить ссылку, чтобы понять ее лучше.

До этого, вот ваш код взорван в полном объеме, если / иначе.

grouperArray.sort(function (a, b) {
    if (a.gsize < b.gsize)
    {
        return -1;
    }
    else if (a.gsize > b.gsize)
    {
        return 1;
    }
    else
    {
        if (a.glow < b.glow)
        {
            return -1;
        }
        else if (a.glow > b.glow)
        {
            return 1;
        }
        return 0;
    }
});
5 голосов
/ 09 октября 2015

Вот реализация для тех, кому может потребоваться что-то более общее, которое будет работать с любым количеством полей.

Array.prototype.sortBy = function (propertyName, sortDirection) {

    var sortArguments = arguments;
    this.sort(function (objA, objB) {

        var result = 0;
        for (var argIndex = 0; argIndex < sortArguments.length && result === 0; argIndex += 2) {

            var propertyName = sortArguments[argIndex];
            result = (objA[propertyName] < objB[propertyName]) ? -1 : (objA[propertyName] > objB[propertyName]) ? 1 : 0;

            //Reverse if sort order is false (DESC)
            result *= !sortArguments[argIndex + 1] ? 1 : -1;
        }
        return result;
    });

}

В принципе, вы можете указать любое количество имени свойства / направления сортировки:

var arr = [{
  LastName: "Doe",
  FirstName: "John",
  Age: 28
}, {
  LastName: "Doe",
  FirstName: "Jane",
  Age: 28
}, {
  LastName: "Foo",
  FirstName: "John",
  Age: 30
}];

arr.sortBy("LastName", true, "FirstName", true, "Age", false);
//Will return Jane Doe / John Doe / John Foo

arr.sortBy("Age", false, "LastName", true, "FirstName", false);
//Will return John Foo / John Doe / Jane Doe
3 голосов
/ 25 мая 2011
grouperArray.sort(function (a, b) {
     var aSize = a.gsize;     
     var bSize = b.gsize;     
     var aLow = a.glow;
     var bLow = b.glow;
     console.log(aLow + " | " + bLow);
     return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0); }); 
3 голосов
/ 25 мая 2011
grouperArray.sort(function (a, b) {
  var aSize = a.gsize;
  var bSize = b.gsize;
  var aLow = a.glow;
  var bLow = b.glow;
  console.log(aLow + " | " + bLow);      
  return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : ( (aLow < bLow ) ? -1 : (aLow > bLow ) ? 1 : 0 );
});
2 голосов
/ 05 июля 2018

Вот реализация, которая использует рекурсию для сортировки по любому количеству полей сортировки от 1 до бесконечности.Вы передаете ему массив результатов, который представляет собой массив объектов результатов для сортировки, и массив сортировки, который представляет собой массив объектов сортировки, определяющих сортировку.У каждого объекта сортировки должен быть ключ "select" для имени ключа, по которому он сортируется, и ключ "order", представляющий собой строку, обозначающую "возрастание" или "убывание".

sortMultiCompare = (a, b, sorts) => {
    let select = sorts[0].select
    let order = sorts[0].order
    if (a[select] < b[select]) {
        return order == 'ascending' ? -1 : 1
    } 
    if (a[select] > b[select]) {
        return order == 'ascending' ? 1 : -1
    }
    if(sorts.length > 1) {
        let remainingSorts = sorts.slice(1)
        return this.sortMultiCompare(a, b, remainingSorts)
    }
    return 0
}

sortResults = (results, sorts) => {
    return results.sort((a, b) => {
        return this.sortMultiCompare(a, b, sorts)
    })
}

// example inputs
const results = [
    {
        "LastName": "Doe",
        "FirstName": "John",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Doe",
        "FirstName": "Jane",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Johnson",
        "FirstName": "Kevin",
        "MiddleName": "Bill"
    }
]

const sorts = [
    {
        "select": "LastName",
        "order": "ascending"
    },
    {
        "select": "FirstName",
        "order": "ascending"
    },
    {
        "select": "MiddleName",
        "order": "ascending"
    }    
]

// call the function like this:
let sortedResults = sortResults(results, sorts)
0 голосов
/ 31 мая 2019

Вот решение для случая, когда у вас есть приоритетный ключ сортировки, который может не существовать в некоторых конкретных элементах, поэтому вам придется сортировать по запасным ключам.

Пример ввода данных ( id2 - приоритетный ключ сортировки):

const arr = [
    {id: 1},
    {id: 2, id2: 3},
    {id: 4},
    {id: 3},
    {id: 10, id2: 2},
    {id: 7},
    {id: 6, id2: 1},
    {id: 5},
    {id: 9, id2: 2},
    {id: 8},
];

И вывод должен быть:

[ { id: 6, id2: 1 },
  { id: 9, id2: 2 },
  { id: 10, id2: 2 },
  { id: 2, id2: 3 },
  { id: 1 },
  { id: 3 },
  { id: 4 },
  { id: 5 },
  { id: 7 },
  { id: 8 } ]

Функция компаратора будет выглядеть так:

arr.sort((a,b) => {
  if(a.id2 || b.id2) {
    if(a.id2 && b.id2) {
      if(a.id2 === b.id2) {
        return a.id - b.id;
      }
      return a.id2 - b.id2;
    }
    return a.id2 ? -1 : 1;
  }
  return a.id - b.id
});

P.S. Если .id из .id2 могут быть нулями, рассмотрите возможность использования typeof.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...