Функция сортировки Javascript. Сортировка сначала
У меня есть массив объектов для сортировки. Каждый объект имеет два параметра: сила и имя
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;
};
Спасибо за вашу помощь.
Ответы
Ответ 1
Разверните функцию сортировки таким образом:
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 <
и >
сравнение по строкам - это алфавитное сравнение.
Ответ 2
Эта маленькая функция часто удобна при сортировке по нескольким клавишам:
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 действительно отсутствует оператор космического корабля Ruby, что делает такие сравнения чрезвычайно элегантными.
Ответ 3
Вы можете связать порядок сортировки с логическим ИЛИ.
objects.sort(function (a, b) {
return a.strength - b.strength || a.name.localeCompare(b.name);
});
Ответ 4
Когда я искал ответ на этот самый вопрос, ответы, которые я нашел в StackOverflow, были не совсем такими, на которые я надеялся. Поэтому я создал простую, многократно используемую функцию, которая делает именно это. Это позволяет вам использовать стандартный Array.sort, но со стилем firstBy(). ThenBy(). ThenBy(). https://github.com/Teun/thenBy.js
PS. Это второй раз, когда я публикую это. Первый раз был удален модератором со словами "Пожалуйста, не делайте рекламных постов для своей работы". Я не уверен, какие здесь правила, но я пытался ответить на этот вопрос. Мне очень жаль, что это моя собственная работа. Не стесняйтесь удалять снова, но, пожалуйста, покажите мне, какое правило применяется.
Ответ 5
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;
};
EDIT: Сортировка по силе, тогда, если сила равна, сортируйте по имени.
Случай, когда сила и имя равны в обоих объектах, не нужно учитывать отдельно, так как окончательный возврат -1 указывает на отношения менее или равные. Результат сортировки будет правильным. Это может заставить его работать быстрее или медленнее, я не знаю. Если вы хотите быть явным, просто замените
return -1;
с
else if (ob1.name < ob2.name) {return -1}
return 0;
Ответ 6
Найдите функцию "sortFn" ниже. Эта функция сортируется по неограниченному числу параметров (например, в С#: 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:
<pre></pre>
Result:
<pre></pre>
Ответ 7
С 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;
}
Ответ 8
Стив ответь, но красивее.
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;
}
Ответ 9
В 2018 году вы можете использовать функцию sort() ES6, которая делает именно то, что вы хотите. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Ответ 10
Как насчет одного длинного и мощного лайнера:
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);
Fields - это массив объектов с полем 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.