Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int
:
int x;
x = 10;
В этом примере переменная x является int
, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.
Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:
Integer num;
num = new Integer(10);
Первая строка объявляет переменную с именем num
, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer
является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».
Во второй строке ключевое слово new
используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num
присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования .
(точка).
Exception
, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num
. Перед созданием объекта вы получите NullPointerException
. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.
Например, вы можете имеют следующий метод:
public void doSomething(SomeObject obj) {
//do something to obj
}
В этом случае вы не создаете объект obj
, скорее предполагая, что он был создан до вызова метода doSomething
. К сожалению, этот метод можно вызвать следующим образом:
doSomething(null);
В этом случае obj
имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException
, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.
Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething
может быть записано как:
/**
* @param obj An optional foo for ____. May be null, in which case
* the result will be ____.
*/
public void doSomething(SomeObject obj) {
if(obj != null) {
//do something
} else {
//do something else
}
}
Наконец, Как определить исключение & amp; причина использования Трассировки стека
Достаточно просто написать собственную функцию сравнения:
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');
Используя lodash или Underscore, его кусок торта
> const sortedList = _.orderBy(objs, [last_nom], [asc]); // asc or desc
Объединив динамическое решение 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;
});
Смените оператор, чтобы он отсортировался по обратному алфавитному порядку.
if(a.count == b.count) return a.name > b.name; else return a.count > b.count;
– p3lim
7 May 2017 в 17:16
Я не видел такого конкретного подхода, поэтому я хотел бы использовать метод сравнения, который мне нравится использовать как для 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