You could use a chained sorting approach by taking the delta of values until it reaches a value not equal to zero.
var data = [{ 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" }];
data.sort(function (a, b) {
return a.city.localeCompare(b.city) || b.price - a.price;
});
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Or, using es6, simply:
data.sort((a, b) => a.city.localeCompare(b.city) || b.price - a.price);
Answer from Nina Scholz on Stack OverflowYou could use a chained sorting approach by taking the delta of values until it reaches a value not equal to zero.
var data = [{ 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" }];
data.sort(function (a, b) {
return a.city.localeCompare(b.city) || b.price - a.price;
});
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Or, using es6, simply:
data.sort((a, b) => a.city.localeCompare(b.city) || b.price - a.price);
for a non-generic, simple solution to your exact problem:
homes.sort(
function(a, b) {
if (a.city === b.city) {
// Price is only important when cities are the same
return b.price - a.price;
}
return a.city > b.city ? 1 : -1;
});
Sort array of objects by multiple properties in Javascript - Stack Overflow
javascript - Sorting an array of objects by property values - Stack Overflow
JavaScript sort array of objects on multiple properties by specific constant values - Stack Overflow
Day 57: How Do You Sort an Array of Objects by Multiple Properties in JavaScript?
If the found text is same for 2 objects, then compare the index of the website of the 2 objects in siteOrder.
data.sort(function (a, b) {
var textA = a.found.toUpperCase();
var textB = b.found.toUpperCase();
var foundOrder = (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
if (foundOrder === 0) {
var indexA = siteOrder.indexOf(a.website);
var indexB = siteOrder.indexOf(b.website);
return (indexA < indexB) ? -1 : (indexA > indexB) ? 1 : 0;
}
return foundOrder;
});
var siteOrder = ['facebook', 'twitter', 'reddit', 'youtube', 'instagram'];
var data = [
{found: 'booker', website: 'reddit'},
{found: 'john', website: 'facebook'},
{found: 'walter', website: 'twitter'},
{found: 'smith', website: 'instagram'},
{found: 'steve', website: 'youtube'},
{found: 'smith', website: 'facebook'},
{found: 'steve', website: 'twitter'},
{found: 'john', website: 'instagram'},
{found: 'walter', website: 'youtube'}
];
// For performance, add a property that is the index of the website in the list
data.forEach(o => o.siteIndex = siteOrder.indexOf(o.website));
// If the `found` of each object is the same, then use the index of the
// website as the sort criteria, otherwise compare the `found` props
data.sort((a, b) =>
a.found === b.found ? a.siteIndex - b.siteIndex : a.found.localeCompare(b.found)
);
// Remove the optimization property
data.forEach(o => delete o.siteIndex);
console.log(data);
For multiple sort criteria you proceed from the first to the last criterion: If the two entries for one criterion are not equal, you can return from the sort function with result -1 or 1. Additionally at the last criterion you also can return 0 for two equal inputs.
Here is an example implementation for your case:
byNameDefault.sort(function (a, b) {
// compare names
var na = a.name.toLowerCase();
var nb = b.name.toLowerCase();
if (na !== nb) {
if (na === 'foo')
return -1;
else if (nb === 'foo')
return 1;
else
return na < nb ? -1 : 1;
}
// compare types
return a.type < b.type ? -1 : a.type > b.type ? 1 : 0;
}
Do this in one expression where the different components are combined with ||; only when one part evaluates to 0, then next one comes into play:
byNameDefault.sort(function (a, b) {
return (b === 'foo') - (a == 'foo') ||
a.name.localeCompare(b.name) ||
a.type.localeCommpare(b.type);
}
Sort homes by price in ascending order:
homes.sort(function(a, b) {
return parseFloat(a.price) - parseFloat(b.price);
});
Or after ES6 version:
homes.sort((a, b) => parseFloat(a.price) - parseFloat(b.price));
Some documentation can be found here.
For descending order, you may use
homes.sort((a, b) => parseFloat(b.price) - parseFloat(a.price));
Here's a more flexible version, which allows you to create reusable sort functions, and sort by any field.
const sort_by = (field, reverse, primer) => {
const key = primer ?
function(x) {
return primer(x[field])
} :
function(x) {
return x[field]
};
reverse = !reverse ? 1 : -1;
return function(a, b) {
return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
}
}
//Now you can sort by any field at will...
const 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:"5",city:"New York",state:"NY",zip:"00010",price:"962500"}];
// Sort by price high to low
console.log(homes.sort(sort_by('price', true, parseInt)));
// Sort by city, case-insensitive, A-Z
console.log(homes.sort(sort_by('city', false, (a) => a.toUpperCase()
)));
Run code snippetEdit code snippet Hide Results Copy to answer Expand
With a point system
Checking = 2
CAD = 1
console.log(
[
{ bankType: "Checking", currency: "USD", amount: 123.45 },
{ bankType: "Saving", currency: "CAD", amount: 1.95 },
{ bankType: "Saving", currency: "USD", amount: 23.31 },
{ bankType: "Checking", currency: "CAD", amount: 1953.1 },
]
.sort((a, b) => {
const pointsA = (a.bankType === "Checking" ? 2 : 0) + (a.currency === "CAD" ? 1 : 0);
const pointsB = (b.bankType === "Checking" ? 2 : 0) + (b.currency === "CAD" ? 1 : 0);
return pointsB - pointsA;
})
);
You can just compare the two in order:
accounts.sort((a, b) =>
a.bankType.localeCompare(b.bankType) || a.currency.localeCompare(b.currency)
);
It's easy enough to write your own comparison function:
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 );
Or inline (c/o Marco Demaio):
objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0))
Or simplified for numeric (c/o Andre Figueiredo):
objs.sort((a,b) => a.last_nom - b.last_nom); // b - a for reverse sort
You can also create a dynamic sort function that sorts objects by their value that you pass:
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;
}
}
So you can have an array of objects like this:
var People = [
{Name: "Name", Surname: "Surname"},
{Name:"AAA", Surname:"ZZZ"},
{Name: "Name", Surname: "AAA"}
];
...and it will work when you do:
People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));
Actually this already answers the question. Below part is written because many people contacted me, complaining that it doesn't work with multiple parameters.
Multiple Parameters
You can use the function below to generate sort functions with multiple sort parameters.
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;
}
}
Which would enable you to do something like this:
People.sort(dynamicSortMultiple("Name", "-Surname"));
Subclassing Array
For the lucky among us who can use ES6, which allows extending the native objects:
class MyArray extends Array {
sortBy(...args) {
return this.sort(dynamicSortMultiple(...args));
}
}
That would enable this:
MyArray.from(People).sortBy("Name", "-Surname");