В некоторых ситуациях regexp может помочь. Вот пример, который я проверил в Oracle, и он работает.
select * from my_table where REGEXP_LIKE (search_column, 'value1|value2')
Но с ним существует ряд недостатков:
Достаточно просто написать собственную функцию сравнения:
function compare(a,b) {
if (a.last_nom < b.last_nom)
return -1;
if (a.last_nom > b.last_nom)
return 1;
return 0;
}
objs.sort(compare);
Или встроенный (c / o Marco Demaio):
objs.sort(function(a,b) {return (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0);} );
Я знаю, что этот вопрос слишком стар, но я не видел никакой реализации, подобной моей. Эта версия основана на символе преобразования Шварца .
function sortByAttribute(array, ...attrs) {
// generate an array of predicate-objects contains
// property getter, and descending indicator
let predicates = attrs.map(pred => {
let descending = pred.charAt(0) === '-' ? -1 : 1;
pred = pred.replace(/^-/, '');
return {
getter: o => o[pred],
descend: descending
};
});
// schwartzian transform idiom implementation. aka: "decorate-sort-undecorate"
return array.map(item => {
return {
src: item,
compareValues: predicates.map(predicate => predicate.getter(item))
};
})
.sort((o1, o2) => {
let i = -1, result = 0;
while (++i < predicates.length) {
if (o1.compareValues[i] < o2.compareValues[i]) result = -1;
if (o1.compareValues[i] > o2.compareValues[i]) result = 1;
if (result *= predicates[i].descend) break;
}
return result;
})
.map(item => item.src);
}
Вот пример того, как его использовать:
let games = [
{ name: 'Pako', rating: 4.21 },
{ name: 'Hill Climb Racing', rating: 3.88 },
{ name: 'Angry Birds Space', rating: 3.88 },
{ name: 'Badland', rating: 4.33 }
];
// sort by one attribute
console.log(sortByAttribute(games, 'name'));
// sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));
В соответствии с вашим примером вам нужно отсортировать по двум полям (фамилия, имя), а не по одному. Вы можете использовать библиотеку Alasql , чтобы сделать этот вид в одной строке:
var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);
Попробуйте этот пример в jsFiddle .
Если у вас есть дубликаты фамилий, вы можете отсортировать их по имени -
obj.sort(function(a,b){
if(a.last_nom< b.last_nom) return -1;
if(a.last_nom >b.last_nom) return 1;
if(a.first_nom< b.first_nom) return -1;
if(a.first_nom >b.first_nom) return 1;
return 0;
});
дополнительные параметры desc для кода Ege Özcan
function dynamicSort(property, desc) {
if (desc) {
return function (a, b) {
return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0;
}
}
return function (a, b) {
return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
}
}
использовать подчеркивание, его маленькое и удивительное ...
sortBy_.sortBy (list, iterator, [context ]) Возвращает отсортированную копию списка, ранжированную в порядке возрастания по результатам запуска каждого значения через итератор. Итератор также может быть строковым именем свойства для сортировки по (например, длине).
var objs = [ { first_nom: 'Lazslo',last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; var sortedObjs = _.sortBy( objs, 'first_nom' );
var sortedObjs = _.sortBy( objs, 'first_nom' );
. objs
будет не сортироваться в результате этого. Функция возвращает отсортированный массив. Это сделает его более явным.
– Jess
9 January 2014 в 06:01
var reverseSortedObjs = _.sortBy( objs, 'first_nom' ).reverse();
– Erdal G.
31 January 2016 в 11:43
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"> </script>
– and-bri
29 May 2017 в 18:28
С учетом исходного примера:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
Сортировка по нескольким полям:
objs.sort(function(left, right) {
var last_nom_order = left.last_nom.localeCompare(right.last_nom);
var first_nom_order = left.first_nom.localeCompare(right.first_nom);
return last_nom_order || first_nom_order;
});
Примечания
a.localeCompare(b)
- универсально поддерживается и возвращает -1,0,1, если a<b
, a==b
, a>b
соответственно. ||
в последней строке дает last_nom
приоритет над first_nom
. var age_order = left.age - right.age;
return -last_nom_order || -first_nom_order || -age_order;
Возможно, вам понадобится преобразовать их в нижний регистр, чтобы предотвратить путаницу.
objs.sort(function (a,b) {
var nameA=a.last_nom.toLowerCase(), nameB=b.last_nom.toLowerCase()
if (nameA < nameB)
return -1;
if (nameA > nameB)
return 1;
return 0; //no sorting
})
Простым способом:
objs.sort(function(a,b) {
return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});
См., что '.toLowerCase()'
необходимо для предотвращения ошибок при сравнении строк.
objs.sort( (a,b) => b.last_nom.toLowerCase() < a.last_nom.toLowerCase() );
– Sertage
24 May 2017 в 15:04
Вместо использования специальной функции сравнения вы также можете создать тип объекта с помощью специального метода toString()
(который вызывается функцией сравнения по умолчанию):
function Person(firstName, lastName) {
this.firtName = firstName;
this.lastName = lastName;
}
Person.prototype.toString = function() {
return this.lastName + ', ' + this.firstName;
}
var persons = [ new Person('Lazslo', 'Jamf'), ...]
persons.sort();
Я просто улучшил динамическую сортировку Ege Özcan для погружения глубоко внутри объектов. Если Data выглядит так:
obj = [
{
a: { a: 1, b: 2, c: 3 },
b: { a: 4, b: 5, c: 6 }
},
{
a: { a: 3, b: 2, c: 1 },
b: { a: 6, b: 5, c: 4 }
}];
, и если вы хотите отсортировать его по свойствам a.a, я думаю, что мое улучшение помогает очень хорошо. Я добавляю новую функциональность к таким объектам:
Object.defineProperty(Object.prototype, 'deepVal', {
enumerable: false,
writable: true,
value: function (propertyChain) {
var levels = propertyChain.split('.');
parent = this;
for (var i = 0; i < levels.length; i++) {
if (!parent[levels[i]])
return undefined;
parent = parent[levels[i]];
}
return parent;
}
});
и изменил функцию return_dynamicSort : И теперь вы можете сортировать по a.a. следующим образом: См. Commplete script in JSFiddle return function (a,b) {
var result = ((a.deepVal(property) > b.deepVal(property)) - (a.deepVal(property) < b.deepVal(property)));
return result * sortOrder;
}
obj.sortBy('a.a');
dynamicSort()
в приведенном выше примере будет содержать заглавные буквы перед строчными буквами. Например, если у меня есть значения APd
, Aklin
и Abe
- результаты в сортировке ASC должны быть Abe
, Aklin
, APd
. Но с вашим примером, результаты APd
, Abe
, Aklin
. В любом случае, чтобы исправить это поведение?
– Lloyd Banks
26 July 2017 в 22:06
var result = a[property].localeCompare(b[property]);
вместо var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
.
– Ege Özcan
6 August 2017 в 08:55
[ { a: 5 }, {a:2}, {}, {a:1} ]
– dzh
19 January 2018 в 05:09
У меня есть часть кода, которая работает для меня:
arr.sort((a, b) => a.name > b.name)
UPDATE: не работает всегда, поэтому это неверно: (
Использование xPrototype: https://github.com/reduardo7/xPrototype/blob/master/README.md#sortbycol1-col2-coln
var o = [
{ Name: 'Lazslo', LastName: 'Jamf' },
{ Name: 'Pig', LastName: 'Bodine' },
{ Name: 'Pirate', LastName: 'Prentice' },
{ Name: 'Pag', LastName: 'Bodine' }
];
// Original
o.each(function (a, b) { console.log(a, b); });
/*
0 Object {Name: "Lazslo", LastName: "Jamf"}
1 Object {Name: "Pig", LastName: "Bodine"}
2 Object {Name: "Pirate", LastName: "Prentice"}
3 Object {Name: "Pag", LastName: "Bodine"}
*/
// Sort By LastName ASC, Name ASC
o.sortBy('LastName', 'Name').each(function(a, b) { console.log(a, b); });
/*
0 Object {Name: "Pag", LastName: "Bodine"}
1 Object {Name: "Pig", LastName: "Bodine"}
2 Object {Name: "Lazslo", LastName: "Jamf"}
3 Object {Name: "Pirate", LastName: "Prentice"}
*/
// Sort by LastName ASC and Name ASC
o.sortBy('LastName'.asc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
0 Object {Name: "Pag", LastName: "Bodine"}
1 Object {Name: "Pig", LastName: "Bodine"}
2 Object {Name: "Lazslo", LastName: "Jamf"}
3 Object {Name: "Pirate", LastName: "Prentice"}
*/
// Sort by LastName DESC and Name DESC
o.sortBy('LastName'.desc, 'Name'.desc).each(function(a, b) { console.log(a, b); });
/*
0 Object {Name: "Pirate", LastName: "Prentice"}
1 Object {Name: "Lazslo", LastName: "Jamf"}
2 Object {Name: "Pig", LastName: "Bodine"}
3 Object {Name: "Pag", LastName: "Bodine"}
*/
// Sort by LastName DESC and Name ASC
o.sortBy('LastName'.desc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
0 Object {Name: "Pirate", LastName: "Prentice"}
1 Object {Name: "Lazslo", LastName: "Jamf"}
2 Object {Name: "Pag", LastName: "Bodine"}
3 Object {Name: "Pig", LastName: "Bodine"}
*/
function compare(propName) {
return function(a,b) {
if (a[propName] < b[propName])
return -1;
if (a[propName] > b[propName])
return 1;
return 0;
};
}
objs.sort(compare("last_nom"));
Пример использования:
objs.sort(sortBy('last_nom'));
Сценарий:
/**
* @description
* Returns a function which will sort an
* array of objects by the given key.
*
* @param {String} key
* @param {Boolean} reverse
* @return {Function}
*/
function sortBy(key, reverse) {
// Move smaller items towards the front
// or back of the array depending on if
// we want to sort the array in reverse
// order or not.
var moveSmaller = reverse ? 1 : -1;
// Move larger items towards the front
// or back of the array depending on if
// we want to sort the array in reverse
// order or not.
var moveLarger = reverse ? -1 : 1;
/**
* @param {*} a
* @param {*} b
* @return {Number}
*/
return function(a, b) {
if (a[key] < b[key]) {
return moveSmaller;
}
if (a[key] > b[key]) {
return moveLarger;
}
return 0;
};
}
Это простая проблема, не знаю, почему у людей такое сложное решение. Простая функция сортировки (на основе алгоритма быстрой сортировки):
function sortObjectsArray(objectsArray, sortKey)
{
// Quick Sort:
var retVal;
if (1 < objectsArray.length)
{
var pivotIndex = Math.floor((objectsArray.length - 1) / 2); // middle index
var pivotItem = objectsArray[pivotIndex]; // value in the middle index
var less = [], more = [];
objectsArray.splice(pivotIndex, 1); // remove the item in the pivot position
objectsArray.forEach(function(value, index, array)
{
value[sortKey] <= pivotItem[sortKey] ? // compare the 'sortKey' proiperty
less.push(value) :
more.push(value) ;
});
retVal = sortObjectsArray(less, sortKey).concat([pivotItem], sortObjectsArray(more, sortKey));
}
else
{
retVal = objectsArray;
}
return retVal;
}
Пример использования:
var myArr =
[
{ val: 'x', idx: 3 },
{ val: 'y', idx: 2 },
{ val: 'z', idx: 5 },
];
myArr = sortObjectsArray(myArr, 'idx');
Я столкнулся с проблемой сортировки массива объектов с изменением приоритета значений, в основном я хочу сортировать массив людей по их возрасту, а затем по фамилии - или просто по фамилии, имени. Я думаю, что это самое простое решение по сравнению с другими ответами.
it 'используется при вызове sortPeoples ([' array ',' of ',' properties '], reverse = false)
///////////////////////example array of peoples ///////////////////////
var peoples = [
{name: "Zach", surname: "Emergency", age: 1},
{name: "Nancy", surname: "Nurse", age: 1},
{name: "Ethel", surname: "Emergency", age: 1},
{name: "Nina", surname: "Nurse", age: 42},
{name: "Anthony", surname: "Emergency", age: 42},
{name: "Nina", surname: "Nurse", age: 32},
{name: "Ed", surname: "Emergency", age: 28},
{name: "Peter", surname: "Physician", age: 58},
{name: "Al", surname: "Emergency", age: 58},
{name: "Ruth", surname: "Registration", age: 62},
{name: "Ed", surname: "Emergency", age: 38},
{name: "Tammy", surname: "Triage", age: 29},
{name: "Alan", surname: "Emergency", age: 60},
{name: "Nina", surname: "Nurse", age: 58}
];
//////////////////////// Sorting function /////////////////////
function sortPeoples(propertyArr, reverse) {
function compare(a,b) {
var i=0;
while (propertyArr[i]) {
if (a[propertyArr[i]] < b[propertyArr[i]]) return -1;
if (a[propertyArr[i]] > b[propertyArr[i]]) return 1;
i++;
}
return 0;
}
peoples.sort(compare);
if (reverse){
peoples.reverse();
}
};
////////////////end of sorting method///////////////
function printPeoples(){
$('#output').html('');
peoples.forEach( function(person){
$('#output').append(person.surname+" "+person.name+" "+person.age+"<br>");
} )
}
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<html>
<body>
<button onclick="sortPeoples(['surname']); printPeoples()">sort by ONLY by surname ASC results in mess with same name cases</button><br>
<button onclick="sortPeoples(['surname', 'name'], true); printPeoples()">sort by surname then name DESC</button><br>
<button onclick="sortPeoples(['age']); printPeoples()">sort by AGE ASC. Same issue as in first case</button><br>
<button onclick="sortPeoples(['age', 'surname']); printPeoples()">sort by AGE and Surname ASC. Adding second field fixed it.</button><br>
<div id="output"></div>
</body>
</html>
Объединив динамическое решение Ege с идеей Vinay, вы получите хорошее надежное решение:
Array.prototype.sortBy = function() {
function _sortByAttr(attr) {
var sortOrder = 1;
if (attr[0] == "-") {
sortOrder = -1;
attr = attr.substr(1);
}
return function(a, b) {
var result = (a[attr] < b[attr]) ? -1 : (a[attr] > b[attr]) ? 1 : 0;
return result * sortOrder;
}
}
function _getSortFunc() {
if (arguments.length == 0) {
throw "Zero length arguments not allowed for Array.sortBy()";
}
var args = arguments;
return function(a, b) {
for (var result = 0, i = 0; result == 0 && i < args.length; i++) {
result = _sortByAttr(args[i])(a, b);
}
return result;
}
}
return this.sort(_getSortFunc.apply(null, arguments));
}
Использование:
// Utility for printing objects
Array.prototype.print = function(title) {
console.log("************************************************************************");
console.log("**** "+title);
console.log("************************************************************************");
for (var i = 0; i < this.length; i++) {
console.log("Name: "+this[i].FirstName, this[i].LastName, "Age: "+this[i].Age);
}
}
// Setup sample data
var arrObj = [
{FirstName: "Zach", LastName: "Emergency", Age: 35},
{FirstName: "Nancy", LastName: "Nurse", Age: 27},
{FirstName: "Ethel", LastName: "Emergency", Age: 42},
{FirstName: "Nina", LastName: "Nurse", Age: 48},
{FirstName: "Anthony", LastName: "Emergency", Age: 44},
{FirstName: "Nina", LastName: "Nurse", Age: 32},
{FirstName: "Ed", LastName: "Emergency", Age: 28},
{FirstName: "Peter", LastName: "Physician", Age: 58},
{FirstName: "Al", LastName: "Emergency", Age: 51},
{FirstName: "Ruth", LastName: "Registration", Age: 62},
{FirstName: "Ed", LastName: "Emergency", Age: 38},
{FirstName: "Tammy", LastName: "Triage", Age: 29},
{FirstName: "Alan", LastName: "Emergency", Age: 60},
{FirstName: "Nina", LastName: "Nurse", Age: 54}
];
//Unit Tests
arrObj.sortBy("LastName").print("LastName Ascending");
arrObj.sortBy("-LastName").print("LastName Descending");
arrObj.sortBy("LastName", "FirstName", "-Age").print("LastName Ascending, FirstName Ascending, Age Descending");
arrObj.sortBy("-FirstName", "Age").print("FirstName Descending, Age Ascending");
arrObj.sortBy("-Age").print("Age Descending");
С 2018 года существует гораздо более короткое и элегантное решение. Просто используйте. Array.prototype.sort () .
Пример:
var items = [
{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic', value: 13 },
{ name: 'Zeros', value: 37 }
];
// sort by value
items.sort(function (a, b) {
return a.value - b.value;
});
As of 2018
Я думаю, вы имеете в виду «По состоянию на 1997 год», когда была выпущена спецификация для 1-го издания ECMAScript и определена Array.prototype.sort()
... См. §15.4.4.5 на стр. 79
– Patrick Roberts
18 July 2018 в 09:27
Не поймите, почему люди делают это настолько сложным:
objs.sort(function(a, b){
return a.last_nom > b.last_nom;
});
Для более строгих движков:
objs.sort(function(a, b){
return a.last_nom == b.last_nom ? 0 : +(a.last_nom > b.last_nom) || -1;
});
Смените оператор, чтобы он отсортировался по обратному алфавитному порядку.
Я не видел такого конкретного подхода, поэтому я хотел бы использовать метод сравнения, который мне нравится использовать как для string
, так и для number
:
const objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
const sortBy = fn => (a, b) => -(fn(a) < fn(b)) || +(fn(a) > fn(b))
const getLastName = o => o.last_nom
const sortByLastName = sortBy(getLastName)
objs.sort(sortByLastName)
console.log(objs.map(getLastName))
Вот объяснение sortBy()
:
sortBy()
принимает параметр fn
, который выбирает какое значение для объекта для использования в качестве сравнения и возвращает функцию, которая может передаются непосредственно на Array.prototype.sort()
. В этом примере мы используем o.last_nom
как значение для сравнения, поэтому всякий раз, когда мы получаем два объекта через Array.prototype.sort()
, такие как
{ first_nom: 'Lazslo', last_nom: 'Jamf' }
и
{ first_nom: 'Pig', last_nom: 'Bodine' }
мы используем
(a, b) => -(fn(a) < fn(b)) || +(fn(a) > fn(b))
для их сравнения.
Вспоминая, что fn = o => o.last_nom
, мы можем развернуть функцию сравнения с эквивалентом
(a, b) => -(a.last_nom < b.last_nom) || +(a.last_nom > b.last_nom)
. Логическое Оператор OR ||
имеет функцию короткого замыкания, которая здесь очень полезна. Из-за того, как это работает, тело функции выше означает
if (a.last_nom < b.last_nom) return -1
return +(a.last_nom > b.last_nom)
Итак, если a < b
мы возвращаем -1
, в противном случае, если a > b
, то мы возвращаем +1
, но если a == b
, тогда a < b
и a > b
являются ложными, поэтому он возвращает +0
.
В качестве дополнительного бонуса здесь эквивалент в ECMAScript 5.1 без функций стрелок, что, к сожалению, не совсем так:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
var sortBy = function (fn) {
return function (a, b) {
return -(fn(a) < fn(b)) || +(fn(a) > fn(b))
}
}
var getLastName = function (o) { return o.last_nom }
var sortByLastName = sortBy(getLastName)
objs.sort(sortByLastName)
console.log(objs.map(getLastName))
Еще одна опция:
var someArray = [...];
function generateSortFn(prop, reverse) {
return function (a, b) {
if (a[prop] < b[prop]) return reverse ? 1 : -1;
if (a[prop] > b[prop]) return reverse ? -1 : 1;
return 0;
};
}
someArray.sort(generateSortFn('name', true));
сортирует по возрастанию по умолчанию.
objs.sort(function(a,b){return b.last_nom>a.last_nom})
Lodash.js (надмножество Underscore.js )
Хорошо не добавлять рамки для каждой простой части логики, но полагаться
Lodash выпускает очень чистый код и способствует более функциональному программированию , который приводит к тому, что он работает на хорошо проверенных средах утилиты, ускоряет разработку и уменьшает количество написанных ошибок. в меньшем количестве ошибок. В одном взгляде становится ясно, что за цель, если код.
Проблема OP может быть просто решена как:
const sortedObjs = _.sortBy(objs, 'last_nom');
Подробнее? Например. у нас есть следующий вложенный объект:
const users = [
{ 'user': {'name':'fred', 'age': 48}},
{ 'user': {'name':'barney', 'age': 36 }},
{ 'user': {'name':'wilma'}},
{ 'user': {'name':'betty', 'age': 32}}
];
Теперь мы можем использовать стенографию _. свойство user.age
, чтобы указать путь к свойству, которое должно быть сопоставлено. Мы будем сортировать объекты пользователя по вложенному возрасту. Да, это позволяет сопоставлять вложенные свойства!
const sortedObjs = _.sortBy(users, ['user.age']);
Хотите, чтобы это было отменено? Нет проблем. Используйте _. Reverse .
const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));
Хотите комбинировать оба с помощью Chaining ?
const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();
Использование Ramda,
npm установка ramda
import R from 'ramda'
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
var ascendingSortedObjs = R.sortBy(R.prop('last_nom'), objs)
var descendingSortedObjs = R.reverse(ascendingSortedObjs)
Здесь много хороших ответов, но я хотел бы отметить, что их можно очень просто расширить, чтобы добиться более сложной сортировки. Единственное, что вам нужно сделать, это использовать оператор OR для цепочки сравнения, например:
objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )
Где fn1
, fn2
, ... являются функциями сортировки, которые возвращают [- 1,0,1]. Это приводит к «сортировке по fn1», «сортировке по fn2», которая в значительной степени равна ORDER BY в SQL.
Это решение основано на поведении оператора ||
, который оценивает значение первое оцениваемое выражение, которое может быть преобразовано в true .
Простейшая форма имеет только одну встроенную функцию:
// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )
Имея два шага с last_nom
, порядок сортировки first_nom
будет выглядеть так:
// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) ||
a.first_nom.localeCompare(b.first_nom) )
Общая функция сравнения может быть примерно такой:
// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])
Эта функция может быть расширена для поддержки числовых полей , чувствительность к регистру, произвольные типы данных и т. д.
Вы можете использовать его с привязкой к ним по приоритету сортировки:
// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> cmp(a,b, "last_nom") || cmp(a,b, "first_nom") )
// ORDER_BY last_nom, first_nom DESC
objs.sort((a,b)=> cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )
// ORDER_BY last_nom DESC, first_nom DESC
objs.sort((a,b)=> -cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )
. Дело в том, что чистый JavaScript с функциональным подходом может принять вас долгий путь без внешних библиотек или сложного кода. Это также очень эффективно, так как не нужно выполнять синтаксический анализ строк
В ES6 / ES2015 или более поздней версии вы можете сделать так:
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
last_nom
используйте только число в массиве: 1
?
– and-bri
29 May 2017 в 18:15
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom, undefined, {numberic: true}));
– scipper
9 January 2018 в 09:49
Простое и быстрое решение этой проблемы с использованием наследования прототипа:
Array.prototype.sortBy = function(p) {
return this.slice(0).sort(function(a,b) {
return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
});
}
Пример / Использование
objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}];
objs.sortBy('age');
// Returns
// [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}]
objs.sortBy('name');
// Returns
// [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}]
Обновление: больше не изменяет исходный массив.
Поскольку вы, вероятно, сталкиваетесь с более сложными структурами данных, такими как этот массив, я бы расширил решение.
Более вместительная версия на основе @ ege-Özcan очень симпатичного ответа .
Проблема
Я столкнулся с ниже и не мог ее изменить. Я также не хотел временно сгладить объект. Я также не хотел использовать underscore / lodash, главным образом по соображениям производительности и забавой для его реализации.
var People = [ {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"}, {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"}, {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"} ];
Цель
Цель состоит в том, чтобы отсортировать ее в основном с помощью
People.Name.name
и, во-вторых,People.Name.surname
Препятствия
Теперь в базовом решении используется скобка для вычисления свойств для динамического сортировки. Здесь, однако, нам также придется динамически создавать условные обозначения скобок, так как вы ожидаете, что некоторые из них
People['Name.name']
будут работать, а это не так.С другой стороны, выполнение
People['Name']['name']
является статическим и позволяет вам спуститься на n -й уровень.Решение
Основным дополнением здесь будет спуск по дереву объектов и определение значения последнего листа, вы должны указать, а также любой промежуточный лист.
var People = [ {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"}, {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"}, {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"} ]; People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname'])); // Results in... // [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' }, // { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' }, // { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ] // same logic as above, but strong deviation for dynamic properties function dynamicSort(properties) { var sortOrder = 1; // determine sort order by checking sign of last element of array if(properties[properties.length - 1][0] === "-") { sortOrder = -1; // Chop off sign properties[properties.length - 1] = properties[properties.length - 1].substr(1); } return function (a,b) { propertyOfA = recurseObjProp(a, properties) propertyOfB = recurseObjProp(b, properties) var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0; return result * sortOrder; }; } /** * Takes an object and recurses down the tree to a target leaf and returns it value * @param {Object} root - Object to be traversed. * @param {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child'] * @param {Number} index - Must not be set, since it is implicit. * @return {String|Number} The property, which is to be compared by sort. */ function recurseObjProp(root, leafs, index) { index ? index : index = 0 var upper = root // walk down one level lower = upper[leafs[index]] // Check if last leaf has been hit by having gone one step too far. // If so, return result from last step. if (!lower) { return upper } // Else: recurse! index++ // HINT: Bug was here, for not explicitly returning function // https://stackoverflow.com/a/17528613/3580261 return recurseObjProp(lower, leafs, index) } /** * Multi-sort your array by a set of properties * @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child'] * @return {Number} Number - number for sort algorithm */ function dynamicMultiSort() { var args = Array.prototype.slice.call(arguments); // slight deviation to base return function (a, b) { var i = 0, result = 0, numberOfProperties = args.length; // REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature // Consider: `.forEach()` while(result === 0 && i < numberOfProperties) { result = dynamicSort(args[i])(a, b); i++; } return result; } }
Пример
Рабочий пример в JSBin
dynamicSort()
в приведенном выше примере будет содержать заглавные буквы перед строчными буквами. Например, если у меня есть значения APd
, Aklin
и Abe
- результаты в сортировке ASC должны быть Abe
, Aklin
, APd
. Но с вашим примером, результаты APd
, Abe
, Aklin
. В любом случае, чтобы исправить это поведение?
– Lloyd Banks
26 July 2017 в 22:06
var result = a[property].localeCompare(b[property]);
вместо var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
.
– Ege Özcan
6 August 2017 в 08:55
[ { a: 5 }, {a:2}, {}, {a:1} ]
– dzh
19 January 2018 в 05:09
return a.last_nom.localeCompare(b.last_nom)
тоже будет работать. – Cerbrus 14 February 2013 в 12:37return a.value - b.value;
(ASC) – Andre Figueiredo 8 January 2014 в 14:06localeCompare
важен при использовании акцентированных символов на иностранных языках и более изящных. – Marcos Lima 1 June 2016 в 16:38