Mam tablicę obiektów JavaScript:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
Jak mogę posortować je według wartości last_nom
w JavaScript?
Wiem o sort(a,b)
, ale wydaje się, że tylko działa na ciągach i liczbach. Czy muszę dodać metodę toString()
do moich obiektów?
28 odpowiedzi
Jest wystarczająco łatwy, aby napisać własną funkcję porównania:
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 );
Lub inline (C / O Marco Demaio):
objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0));
Możesz także utworzyć funkcję sortowania dynamicznego, która sortuje obiekty według ich wartości, którą mijasz:
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
/* next line works with strings and numbers,
* and you may want to customize it to your needs
*/
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
Więc możesz mieć taką tablicę obiektów:
var People = [
{Name: "Name", Surname: "Surname"},
{Name:"AAA", Surname:"ZZZ"},
{Name: "Name", Surname: "AAA"}
];
... I będzie działać, gdy zrobisz:
People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));
Właściwie to już odpowiada na pytanie. Poniżej części jest napisana, ponieważ wielu ludzi skontaktowała się ze mną, narzekając, że Nie działa z wieloma parametrami.
Wiele parametrów.
Możesz użyć poniższej funkcji, aby wygenerować funkcje sortowania z wieloma parametrami sortowania.
function dynamicSortMultiple() {
/*
* save the arguments object as it will be overwritten
* note that arguments object is an array-like object
* consisting of the names of the properties to sort by
*/
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
/* try getting a different result from 0 (equal)
* as long as we have extra properties to compare
*/
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}
Co pozwoli ci zrobić coś takiego:
People.sort(dynamicSortMultiple("Name", "-Surname"));
Tablica podklasy
Na szczęście wśród nas, którzy mogą korzystać z ES6, co pozwala rozszerzyć rodzime obiekty:
class MyArray extends Array {
sortBy(...args) {
return this.sort(dynamicSortMultiple.apply(null, args));
}
}
To umożliwiłoby to:
MyArray.from(People).sortBy("Name", "-Surname");
W ES6 / ES2015 lub później możesz zrobić w ten sposób:
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
Przed ES6 / ES2015
objs.sort(function(a, b) {
return a.last_nom.localeCompare(b.last_nom)
});
Nie rozumiem, dlaczego ludzie robią to tak skomplikowane:
objs.sort(function(a, b){
return a.last_nom > b.last_nom;
});
Dla surowszych silników:
objs.sort(function(a, b){
return a.last_nom == b.last_nom ? 0 : +(a.last_nom > b.last_nom) || -1;
});
Zamień operatora, aby posortował go odwrócone zamówienie alfabetyczne.
Właśnie ulepszam EGE Özcan Sortowanie dynamiczne, aby nurkować głęboko wewnętrzne obiekty. Jeśli dane wyglądają tak:
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 jeśli chcesz go sortować ponad a.a , myślę, że moje ulepszenie pomaga bardzo dobrze. Dodam nowe funkcjonalność do takich obiektów:
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;
}
});
I zmienił _Dynamicsort Funkcja zwrotu
return function (a,b) {
var result = ((a.deepVal(property) > b.deepVal(property)) - (a.deepVal(property) < b.deepVal(property)));
return result * sortOrder;
}
A teraz możesz sortować przez A.a. w ten sposób:
obj.sortBy('a.a');
Zobacz skrypt commplete w jsfiddle
Jeśli masz duplikaty nazwisk, możesz sortować te imię
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;
});
Proste i szybkie rozwiązanie tego problemu za pomocą dziedziczenia prototypu:
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;
});
}
Przykład / użycie
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"}]
Aktualizacja: Nie modyfikuje już oryginalnej tablicy.
Od 2018 r. Istnieje znacznie krótsze i eleganckie rozwiązanie. Po prostu użyj. array.prototype.sort ().
Przykład:
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;
});
Stara odpowiedź, która nie jest poprawna:
arr.sort((a, b) => a.name > b.name)
AKTUALIZACJA
Z komentarza Beauchampa:
arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))
Bardziej czytelny format:
arr.sort((a, b) => {
if (a.name < b.name) return -1
return a.name > b.name ? 1 : 0
})
Bez zagnieżdżonych ternarodowych:
arr.sort((a, b) => a.name < b.name ? - 1 : Number(a.name > b.name))
Objaśnienie: Number()
rzuci true
do 1
i false
do 0
.
Lodash.js (SuperSet of Underscore.js)
Dobrze nie dodawać ramy dla każdego prostego kawałka logiki, ale opierając się na dobrze przetestowanych ramach narzędziowych może przyspieszyć opracowanie i zmniejszyć ilość błędów.
Lodash produkuje bardzo czysty kod i promuje więcej funkcjonalne programowanie styl. W jednym spojrzeniu staje się jasne, jakie jest zamiar kodu.
Problem OP może być po prostu rozwiązany jako:
const sortedObjs = _.sortBy(objs, 'last_nom');
Więcej informacji? Na przykład. Mamy podążał za zagnieżdżonym obiektem:
const users = [
{ 'user': {'name':'fred', 'age': 48}},
{ 'user': {'name':'barney', 'age': 36 }},
{ 'user': {'name':'wilma'}},
{ 'user': {'name':'betty', 'age': 32}}
];
Teraz możemy używać _.Property Shorthand {x0}}, aby określić ścieżkę do właściwości, która powinna być dopasowana. Sortujemy obiekty użytkownika przez nieruchomość zagnieżdżenia. Tak, pozwala na zagnieżdżone pasujące do nieruchomości!
const sortedObjs = _.sortBy(users, ['user.age']);
Chcesz odwrócić? Nie ma problemu. Użyj _.Reverse.
const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));
Chcesz połączyć zarówno za pomocą łańcuch?
const { chain } = require('lodash');
const sortedObjs = chain(users).sortBy('user.age').reverse().value();
Lub kiedy wolisz przepływ nad łańcuchem
const { flow, reverse, sortBy } = require('lodash/fp');
const sortedObjs = flow([sortBy('user.age'), reverse])(users);
Nie widziałem, że te szczególne podejście sugerowało, więc oto metodę porównania tchanu, które lubię używać, które działa zarówno dla string
i 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) => {
const fa = fn(a)
const fb = fn(b)
return -(fa < fb) || +(fa > fb)
}
const getLastName = o => o.last_nom
const sortByLastName = sortBy(getLastName)
objs.sort(sortByLastName)
console.log(objs.map(getLastName))
Oto wyjaśnienie sortBy()
:
sortBy()
Akceptuje fn
, który wybiera wartość z obiektu, aby użyć jako porównania i zwraca funkcję, która może być przekazywana bezpośrednio do Array.prototype.sort()
. W tym przykładzie, używamy o.last_nom
jako wartość dla porównania, więc za każdym razem, gdy otrzymamy dwa obiekty za pomocą Array.prototype.sort()
takie jak
{ first_nom: 'Lazslo', last_nom: 'Jamf' }
I
{ first_nom: 'Pig', last_nom: 'Bodine' }
Używamy
(a, b) => {
const fa = fn(a)
const fb = fn(b)
return -(fa < fb) || +(fa > fb)
}
Porównać je.
Pamiętając, że fn = o => o.last_nom
, możemy rozszerzyć funkcję porównania do odpowiednika
(a, b) => {
const fa = a.last_nom
const fb = b.last_nom
return -(fa < fb) || +(fa > fb)
}
Operator logiczny lub ||
ma funkcjonalność zwarcia, która jest bardzo przydatna tutaj. Ze względu na to, jak działa, ciało funkcji powyżej oznacza
if (fa < fb) return -1
return +(fa > fb)
Więc jeśli fa < fb
Wrócimy -1
, w przeciwnym razie, jeśli fa > fb
wówczas wracamy +1
, ale jeśli fa == fb
, a następnie fa > fb
i fa > fb
} Czy false
, więc zwraca +0
.
Jako dodatkowy bonus, oto odpowiednik w ECMASCRIPT 5 bez funkcji strzałek, który jest niestety więcej pełniejszy:
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) {
var fa = fn(a)
var fb = fn(b)
return -(fa < fb) || +(fa > fb)
}
}
var getLastName = function (o) { return o.last_nom }
var sortByLastName = sortBy(getLastName)
objs.sort(sortByLastName)
console.log(objs.map(getLastName))
Zamiast korzystać z niestandardowej funkcji porównania, można również utworzyć typ obiektu z metodą niestandardową {X0}} (która jest wywołana przez domyślną funkcję porównania):
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();
Możesz użyć
Najłatwiej: Lodash
(https://lodash.com/docs/4.17.10#orderby)
Ta metoda jest jak _.sortby, z wyjątkiem tego, że pozwala na określenie zleceń sortowania itererów do sortowania. Jeśli zamówienia są nieokreślone, wszystkie wartości są sortowane w kolejności rosnącej. W przeciwnym razie określ kolejność "DESC" dla malejącego lub "ASC" dla rosnących kolejności sortowania odpowiednich wartości.
Argumenty
Kolekcja (tablica | obiekt): Kolekcja do itera. [ITERESES = [_. Identity]] (tablica [] | Funkcja [] | obiekt [] | String []): Iteria do sortowania. [Zamówienia] (ciąg []): Sortowanie poleceń iteracji.
Zwroty
(Array): Zwraca nową sortowaną tablicę.
var _ = require('lodash');
var homes = [
{"h_id":"3",
"city":"Dallas",
"state":"TX",
"zip":"75201",
"price":"162500"},
{"h_id":"4",
"city":"Bevery Hills",
"state":"CA",
"zip":"90210",
"price":"319250"},
{"h_id":"6",
"city":"Dallas",
"state":"TX",
"zip":"75000",
"price":"556699"},
{"h_id":"5",
"city":"New York",
"state":"NY",
"zip":"00010",
"price":"962500"}
];
_.orderBy(homes, ['city', 'state', 'zip'], ['asc', 'desc', 'asc']);
Jest tu wiele dobrych odpowiedzi, ale chciałbym zwrócić uwagę, że można je rozszerzyć, aby uzyskać wiele bardziej złożonych sortowania. Jedyną rzeczą, którą musisz zrobić, to użyć funkcji porównania lub funkcji operatora do łańcucha:
objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )
Gdzie fn2
, fn2
, ... są funkcjami sortowania, które zwracają [-1,0,1]. Powoduje to "sortowanie przez FN1", "Sortowanie przez FN2", co jest prawie równe zamówić w SQL.
To rozwiązanie opiera się na operatorze ||
, który ocenia się do Pierwsze ocenione wyrażenie, które można konwertować na true.
Najprostsza forma ma tylko jedną w taką funkcję:
// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )
Mając dwa kroki z last_nom
, first_nom
porządek sortowania wyglądałby tak:
// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) ||
a.first_nom.localeCompare(b.first_nom) )
Ogólna funkcja porównania może być taka:
// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])
Funkcja ta może zostać rozszerzona na wsparcie pól numerycznych, czułość przypadku, dowolnych typów danych itp.
Możesz je wykorzystać z łańcuchem ich według priorytetu sortowania:
// 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") )
Chodzi o to, że czysty JavaScript z podejściem funkcjonalnym może zabrać Ci długą drogę bez bibliotek zewnętrznych lub złożonego kodu. Jest również bardzo skuteczny, ponieważ nie trzeba zrobić parsowanie ciągów
Przykładowe zastosowanie:
objs.sort(sortBy('last_nom'));
Scenariusz:
/**
* @description
* Returns a function which will sort an
* array of objects by the given key.
*
* @param {String} key
* @param {Boolean} reverse
* @return {Function}
*/
const 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.
const 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.
const moveLarger = reverse ? -1 : 1;
/**
* @param {*} a
* @param {*} b
* @return {Number}
*/
return (a, b) => {
if (a[key] < b[key]) {
return moveSmaller;
}
if (a[key] > b[key]) {
return moveLarger;
}
return 0;
};
};
Sortowanie (więcej) Kompleksowe tablice obiektów
Ponieważ prawdopodobnie napotkasz bardziej złożone struktury danych, takie jak ta tablica, rozszerzyłbym rozwiązanie.
TL; DR
Są bardziej wtyczkową w oparciu o @ Ege-Özcan jest bardzo piękny Odpowiedź.
Problem
Spotkałem poniżej i nie mogłem go zmienić. Nie chciałem tymczasowo spłaszczyć obiektu. Nie chciałem też używać podkreślenia / Lodash, głównie ze względów wydajności i zabawy, aby sam go wdrożyć.
var People = [
{Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
{Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
{Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
Cel
Celem jest posortowanie go głównie przez People.Name.name
i wtórnie przez People.Name.surname
Przeszkody
Teraz w rozwiązaniu bazowym wykorzystuje notację wspornika, aby obliczyć właściwości do ich dynamicznie. Tutaj jednak będziemy musieli skonstruować notacji wspornika również dynamicznie, ponieważ spodziewałbyś się, że niektórzy People['Name.name']
będzie działać - co nie.
Po prostu robienie People['Name']['name']
, z drugiej strony jest statyczne i pozwala zejść do poziomu n -th.
Rozwiązanie
Głównym dodatkiem będzie przejść do drzewa obiektowego i określi wartość ostatniego liścia, musisz określić, a także dowolny liść pośredni.
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;
}
}
Przykład
Przykład roboczy On Jsbin
Jeszcze jedna opcja:
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));
Sortuje domyślnie rosnące.
Prosty sposób:
objs.sort(function(a,b) {
return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});
Zobacz, że '.toLowerCase()'
jest konieczne, aby zapobiec błędom w porównaniu ciągów.
Prosta funkcja, która sortująca tablicę obiektu przez nieruchomość
function sortArray(array, property, direction) {
direction = direction || 1;
array.sort(function compare(a, b) {
let comparison = 0;
if (a[property] > b[property]) {
comparison = 1 * direction;
} else if (a[property] < b[property]) {
comparison = -1 * direction;
}
return comparison;
});
return array; // Chainable
}
Stosowanie:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
sortArray(objs, "last_nom"); // Asc
sortArray(objs, "last_nom", -1); // Desc
Dodatkowe DESC Params dla EGE Özcan Kod
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;
}
}
Łącząc dynamiczne rozwiązanie EGE z pomysłem Vinay, otrzymasz ładny solidny rozwiązanie:
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));
}
Stosowanie:
// 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");
objs.sort(function(a,b){return b.last_nom>a.last_nom})
Abording twój przykład, musisz sortować przez dwa pola (nazwisko, imię), a następnie jeden. Możesz użyć alasql biblioteka, aby tego rodzaju w jednej linii:
var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);
Spróbuj tego przykładu w Jsfiddle.
Za pomocą ramdy,
NPM Zainstaluj 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)
Biorąc pod uwagę oryginalny przykład:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
Sortuj według wielu pól:
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;
});
Uwagi
- {{X0}. ,
a==b
,a>b
odpowiednio. ||
W ostatniej linii dajelast_nom
priorytet nadfirst_nom
.- Odejmowanie działa na polach numerycznych:
var age_order = left.age - right.age;
- Negować do odwrotnej kolejności,
return -last_nom_order || -first_nom_order || -age_order;
Może być konieczne przekonwertowanie ich na małe litery, aby zapobiec zamieszaniu.
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
})
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"));
Jest to prosty problem, nie wiem, dlaczego ludzie mają takie złożone rozwiązanie.
Prosta funkcja sortowania (na podstawie Quick-sort algorytm):
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;
}
Użyj przykładu:
var myArr =
[
{ val: 'x', idx: 3 },
{ val: 'y', idx: 2 },
{ val: 'z', idx: 5 },
];
myArr = sortObjectsArray(myArr, 'idx');