Функция сортировки Javascript. Сортировать по первому, затем по второму - PullRequest
50 голосов
/ 07 февраля 2012

У меня есть массив объектов для сортировки. Каждый объект имеет два параметра: Сила и Имя

objects = []
object[0] = {strength: 3, name: "Leo"}
object[1] = {strength: 3, name: "Mike"}

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

function sortF(ob1,ob2) {
  if (ob1.strength > ob2.strength) {return 1}
  else if (ob1.strength < ob2.strength){return -1}
  return 0;
};

Спасибо за вашу помощь.

Ответы [ 10 ]

74 голосов
/ 07 февраля 2012

Расширьте свою функцию сортировки таким образом:

function sortF(ob1,ob2) {
    if (ob1.strength > ob2.strength) {
        return 1;
    } else if (ob1.strength < ob2.strength) { 
        return -1;
    }

    // Else go to the 2nd item
    if (ob1.name < ob2.name) { 
        return -1;
    } else if (ob1.name > ob2.name) {
        return 1
    } else { // nothing to split them
        return 0;
    }
}

A < и > сравнение по строкам - это буквенное сравнение.

45 голосов
/ 07 февраля 2012

Эта маленькая функция часто удобна при сортировке по нескольким клавишам:

cmp = function(a, b) {
    if (a > b) return +1;
    if (a < b) return -1;
    return 0;
}

или, более кратко,

cmp = (a, b) => (a > b) - (a < b)

Примените ее следующим образом:

array.sort(function(a, b) { 
    return cmp(a.strength,b.strength) || cmp(a.name,b.name)
})

В Javascript действительно отсутствует оператор космического корабля Руби , что делает такие сравнения чрезвычайно элегантными.

20 голосов
/ 05 октября 2016

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

objects.sort(function (a, b) {
    return a.strength - b.strength || a.name.localeCompare(b.name);
});
7 голосов
/ 05 августа 2013

Когда я искал ответ на этот вопрос, ответы, которые я нашел в StackOverflow, были не совсем такими, на которые я надеялся.Поэтому я создал простую, многократно используемую функцию, которая делает именно это.Он позволяет использовать стандартный Array.sort, но со стилем firstBy (). ThenBy (). ThenBy ().https://github.com/Teun/thenBy.js

PS.Это второй раз, когда я публикую это.Первый раз был удален модератором со словами «Пожалуйста, не делайте рекламных постов для своей работы».Я не уверен, какие здесь правила, но я пытался ответить на этот вопрос.Мне очень жаль, что это моя собственная работа.Не стесняйтесь удалять снова, но, пожалуйста, покажите мне, какое правило применяется.

1 голос
/ 07 февраля 2012
function sortF(ob1,ob2) {
  if (ob1.strength > ob2.strength) {return 1}
  else if (ob1.strength < ob2.strength) {return -1}
  else if (ob1.name > ob2.name) {return 1}
  return -1;
};

РЕДАКТИРОВАТЬ: Сортировать по силе, а затем, если сила равна, сортировать по имени. Случай, когда сила и имя в обоих объектах одинаковы, не нужно учитывать отдельно, поскольку окончательный возврат -1 указывает на отношение меньше или равно. Результат такого рода будет правильным. Это может заставить его работать быстрее или медленнее, я не знаю. Если вы хотите быть явным, просто замените

return -1;

с

else if (ob1.name < ob2.name) {return -1}
return 0;
0 голосов
/ 14 февраля 2019

Как насчет одного длинного и мощного вкладчика:

const orderByMultipleFactory = (fields) => (a, b) => fields.reduce((acc, {name, asc = true, compareFn}) => acc || (compareFn ? compareFn(a, b) : (isString(a[name]) ? (asc ? a[name].localeCompare(b[name]) : b[name].localeCompare(a[name])) : (asc ? a[name] - b[name] : b[name] - a[name]))), 0);

Поля - это массив объектов с полем name, которое задает свойство объекта, а затем необязательно asc и compareFn для управления направлением или переопределения метода сравнения по умолчанию.
По умолчанию строки сравниваются с помощью localCompare, а все остальное - просто a - b.

Пример:

[{a: 2, b: 'y'}, {a: 3, b: 'x'}, {a: 2, b: 'z'}]
  .sort(orderByMultipleFactory([{name: 'a', asc: false}, {name: 'b'}]))
// result is sorted by "a" descending and equal records by "b" ascending.
0 голосов
/ 26 декабря 2018

В 2018 году вы можете использовать функцию sort () ES6, которая делает именно то, что вы хотите. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

0 голосов
/ 07 ноября 2018

ответ Стива, но красивее.

objects.sort(function(a,b)
{
  if(a.strength > b.strength) {return  1;}
  if(a.strength < b.strength) {return -1;}
  if(a.name     > b.name    ) {return  1;}
  if(a.name     < b.name    ) {return -1;}
  return 0;
}
0 голосов
/ 04 января 2018

С ES6 вы можете сделать

array.sort(function(a, b) { 
 return SortFn(a.strength,b.strength) || SortFn(a.name,b.name)
})

 private sortFn(a, b): number {
    return a === b ? 0 : a < b ? -1 : 1;
}
0 голосов
/ 19 ноября 2015

Найдите функцию sortFn ниже.Эта функция сортирует по неограниченному количеству параметров (например, в c #: SortBy (...). ThenBy (...). ThenByDesc (...)).

function sortFn() {
    var sortByProps = Array.prototype.slice.call(arguments),
        cmpFn = function(left, right, sortOrder) {
            var sortMultiplier = sortOrder === "asc" ? 1 : -1;

            if (left > right) {
                return +1 * sortMultiplier;
            }
            if (left < right) {
                return -1 * sortMultiplier;
            }
            return 0;
        };


    return function(sortLeft, sortRight) {
        // get value from object by complex key
        var getValueByStr = function(obj, path) {
            var i, len;

            //prepare keys
            path = path.replace('[', '.');
            path = path.replace(']', '');
            path = path.split('.');

            len = path.length;

            for (i = 0; i < len; i++) {
                if (!obj || typeof obj !== 'object') {
                    return obj;
                }
                obj = obj[path[i]];
            }

            return obj;
        };

        return sortByProps.map(function(property) {
            return cmpFn(getValueByStr(sortLeft, property.prop), getValueByStr(sortRight, property.prop), property.sortOrder);
        }).reduceRight(function(left, right) {
            return right || left;
        });
    };
}

var arr = [{
    name: 'marry',
    LocalizedData: {
        'en-US': {
            Value: 10000
        }
    }
}, {
    name: 'larry',
    LocalizedData: {
        'en-US': {
            Value: 2
        }
    }
}, {
    name: 'marry',
    LocalizedData: {
        'en-US': {
            Value: 100
        }
    }
}, {
    name: 'larry',
    LocalizedData: {
        'en-US': {
            Value: 1
        }
    }
}];
document.getElementsByTagName('pre')[0].innerText = JSON.stringify(arr)

arr.sort(sortFn({
    prop: "name",
    sortOrder: "asc"
}, {
    prop: "LocalizedData[en-US].Value",
    sortOrder: "desc"
}));

document.getElementsByTagName('pre')[1].innerText = JSON.stringify(arr)
pre {
    font-family: "Courier New" Courier monospace;
    white-space: pre-wrap;
}
Before:
Результат:
   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...