# Javascript sort function. Sort by First then by Second

I have an array of objects to sort.Each object has two parameters: Strength and Name

``````objects = []
object = {strength: 3, name: "Leo"}
object = {strength: 3, name: "Mike"}
``````

I want to sort first by Strength and then by name alphabetically. I am using the following code to sort by the first parameter. How do I sort then by the second?

``````function sortF(ob1,ob2) {
if (ob1.strength > ob2.strength) {return 1}
else if (ob1.strength < ob2.strength){return -1}
return 0;
};
`````` Expand your sort function to be like this;

``````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 `<` and `>` comparison on strings is an alphabetic comparison. This little function is often handy when sorting by multiple keys:

``````cmp = function(a, b) {
if (a > b) return +1;
if (a < b) return -1;
return 0;
}
``````

or, more concisely,

``````cmp = (a, b) => (a > b) - (a < b)
``````

Apply it like this:

``````array.sort(function(a, b) {
return cmp(a.strength,b.strength) || cmp(a.name,b.name)
})
``````

Javascript is really missing Ruby's spaceship operator, which makes such comparisons extremely elegant. You could chain the sort order with logical OR.

``````objects.sort(function (a, b) {
return a.strength - b.strength || a.name.localeCompare(b.name);
});
`````` Find 'sortFn' function below. This function sorts by unlimited number of parameters(such as in c#: 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').innerText = JSON.stringify(arr)

arr.sort(sortFn({
prop: "name",
sortOrder: "asc"
}, {
prop: "LocalizedData[en-US].Value",
sortOrder: "desc"
}));

document.getElementsByTagName('pre').innerText = JSON.stringify(arr)``````
``````pre {
font-family: "Courier New" Courier monospace;
white-space: pre-wrap;
}``````
``````Before:
<pre></pre>
Result:
<pre></pre>`````` ``````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;
}
`````` In 2018 you can use just sort() ES6 function, that do exactly, what you want. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort When I was looking for an answer to this very question, the answers I found on StackOverflow weren't really what I hoped for. So I created a simple, reusable function that does exactly this. It allows you to use the standard Array.sort, but with firstBy().thenBy().thenBy() style. https://github.com/Teun/thenBy.js

PS. This is the second time I post this. The first time was removed by a moderator saying "Please don't make promotional posts for your own work". I'm not sure what the rules are here, but I was trying to answer this question. I'm very sorry that it is my own work. Feel free to remove again, but please point me to the rule involved then. ``````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: Sort by strength, then if strength is equal, sort by name. The case where strength and name are equal in both objects doesn't need to be accounted for seperately, since the final return of -1 indicates a less-than-or-equal-to relationship. The outcome of the sort will be correct. It might make it run faster or slower, I don't know. If you want to be explicit, just replace

``````return -1;
``````

with

``````else if (ob1.name < ob2.name) {return -1}
return 0;
`````` With ES6 you can do

``````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;
}
``````