[javascript] Sort array by firstname (alphabetically) in Javascript

I got an array (see below for one object in the array) that I need to sort by firstname using JavaScript. How can I do it?

var user = {
   bio: null,
   email:  "[email protected]",
   firstname: "Anna",
   id: 318,
   lastAvatar: null,
   lastMessage: null,
   lastname: "Nickson",
   nickname: "anny"
};

This question is related to javascript

The answer is


Basically you can sort arrays with method sort, but if you want to sort objects then you have to pass function to sort method of array, so I will give you an example using your array

user = [{
bio: "<null>",
email: "[email protected]",
firstname: 'Anna',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "[email protected]",
firstname: 'Senad',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "[email protected]",
firstname: 'Muhamed',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
}];

var ar = user.sort(function(a, b)
{
  var nA = a.firstname.toLowerCase();
  var nB = b.firstname.toLowerCase();

  if(nA < nB)
    return -1;
  else if(nA > nB)
    return 1;
 return 0;
});

for a two factors sort (name and lastname):

_x000D_
_x000D_
users.sort((a, b) => a.name.toLowerCase() < b.name.toLowerCase() ? -1 : a.name.toLowerCase() > b.name.toLowerCase() ? 1 : a.lastname.toLowerCase() < b.lastname.toLowerCase() ? -1 : a.lastname.toLowerCase() > b.lastname.toLowerCase() ? 1 : 0)
_x000D_
_x000D_
_x000D_


If compared strings contain unicode characters you can use localeCompare function of String class like the following:

users.sort(function(a,b){
    return a.firstname.localeCompare(b.firstname);
})

in simply words you can use this method

users.sort(function(a,b){return a.firstname < b.firstname ? -1 : 1});

You can use the in-built array method - sort. This method takes a callback method as a param



    // custom sort function to be passed as param/callback to the Array's sort method
    function myCustomSort(a, b) {
        return (a.toLowerCase() > b.toLowerCase()) ? 1 : -1;
    }

    // Actual method to be called by entity that needs sorting feature
    function sortStrings() {
        var op = Array.prototype.sort.call(arguments, myCustomSort);
    }

    // Testing the implementation
    var sortedArray = sortStrings("Burger", "Mayo1", "Pizza", "boxes", "Apples", "Mayo");
    console.log(sortedArray); //["Apples", "boxes", "Burger", "Mayo", "Mayo1", "Pizza"]


Key Points to be noted for understanding this code.

  1. The custom method, in this case, myCustomSort, should return +1 or -1 for each element pair(from the input array) comparison.
  2. Use toLowerCase()/toUpperCase() in the custom sorting callback method so that case difference does not affect the correctness of the sorting process.

I hope this is clear enough explanation. Feel free to comment if you think, more info is needed.

Cheers!


Nice little ES6 one liner:

users.sort((a, b) => a.firstname !== b.firstname ? a.firstname < b.firstname ? -1 : 1 : 0);

also for both asec and desc sort, u can use this : suppose we have a variable SortType that specify ascending sort or descending sort you want:

 users.sort(function(a,b){
            return   sortType==="asc"? a.firstName.localeCompare( b.firstName): -( a.firstName.localeCompare(  b.firstName));
        })

try

users.sort((a,b)=> (a.firstname>b.firstname)*2-1)

_x000D_
_x000D_
var users = [_x000D_
  { firstname: "Kate", id: 318, /*...*/ },_x000D_
  { firstname: "Anna", id: 319, /*...*/ },_x000D_
  { firstname: "Cristine", id: 317, /*...*/ },_x000D_
]_x000D_
_x000D_
console.log(users.sort((a,b)=> (a.firstname>b.firstname)*2-1) );
_x000D_
_x000D_
_x000D_


underscorejs offers the very nice _.sortBy function:

_.sortBy([{a:1},{a:3},{a:2}], "a")

or you can use a custom sort function:

_.sortBy([{a:"b"},{a:"c"},{a:"a"}], function(i) {return i.a.toLowerCase()})

You can use this for objects

transform(array: any[], field: string): any[] {
return array.sort((a, b) => a[field].toLowerCase() !== b[field].toLowerCase() ? a[field].toLowerCase() < b[field].toLowerCase() ? -1 : 1 : 0);}

You can use something similar, to get rid of case sensitive

users.sort(function(a, b){

  //compare two values
  if(a.firstname.toLowerCase() < b.firstname.toLowerCase()) return -1;
  if(a.firstname.toLowerCase() > b.firstname.toLowerCase()) return 1;
  return 0;

})

Just for the record, if you want to have a named sort-function, the syntax is as follows:

let sortFunction = (a, b) => {
 if(a.firstname < b.firstname) { return -1; }
 if(a.firstname > b.firstname) { return 1; }
 return 0;
})
users.sort(sortFunction)

Note that the following does NOT work:

users.sort(sortFunction(a,b))

My implementation, works great in older ES versions:

sortObject = function(data) {
    var keys = Object.keys(data);
    var result = {};

    keys.sort();

    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];

        result[key] = data[key];
    }

    return result;
};

Shortest possible code with ES6!

users.sort((a, b) => a.firstname.localeCompare(b.firstname))

String.prototype.localeCompare() basic support is universal!


Inspired from this answer,

users.sort((a,b) => (a.firstname  - b.firstname));

We can use localeCompare but need to check the keys as well for falsey values

The code below will not work if one entry has missing lname.

obj.sort((a, b) => a.lname.localeCompare(b.lname))

So we need to check for falsey value like below

_x000D_
_x000D_
let obj=[_x000D_
{name:'john',lname:'doe',address:'Alaska'},_x000D_
{name:'tom',lname:'hopes',address:'California'},_x000D_
{name:'harry',address:'Texas'}_x000D_
]_x000D_
let field='lname';_x000D_
console.log(obj.sort((a, b) => (a[field] || "").toString().localeCompare((b[field] || "").toString())));
_x000D_
_x000D_
_x000D_

OR

we can use lodash , its very simple. It will detect the returned values i.e whether number or string and do sorting accordingly .

import sortBy from 'lodash/sortBy';
sortBy(obj,'name')

https://lodash.com/docs/4.17.5#sortBy


A generalized function can be written like below

    function getSortedData(data, prop, isAsc) {
        return data.sort((a, b) => (a[prop] < b[prop] ? -1 : 1) * (isAsc ? 1 : -1));
   }

you can pass the below parameters

  1. The data which you want to sort
  2. The property in the data by it should be sorted
  3. The last parameter is of boolean type. It checks if you want to sort by ascending or by descending

I'm surprised no one mentioned Collators. You shouldn't use localeCompare unless you have to as it has significantly worse performance.

const collator = new Intl.Collator('zh-CN', { // Chinese Simplified for example
  numeric: true,
  sensitivity: 'base',
});

function sortAsc(a, b) {
  if (typeof a === 'string' && typeof b === 'string') {
    return collator.compare(b, a)
  }

  return b - a;
}

function sortDesc(a, b) {
  if (typeof a === 'string' && typeof b === 'string') {
    return collator.compare(a, b);
  }

  return a - b;
}

A more compact notation:

user.sort(function(a, b){
    return a.firstname === b.firstname ? 0 : a.firstname < b.firstname ? -1 : 1;
})

Pushed the top answers into a prototype to sort by key.

Array.prototype.alphaSortByKey= function (key) {
    this.sort(function (a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    });
    return this;
};

In case we are sorting names or something with special characters, like ñ or áéíóú (commons in Spanish) we could use the params locales (es for spanish in this case ) and options like this:

_x000D_
_x000D_
let user = [{'firstname': 'Az'},{'firstname': 'Áb'},{'firstname':'ay'},{'firstname': 'Ña'},{'firstname': 'Nz'},{'firstname': 'ny'}];_x000D_
_x000D_
_x000D_
user.sort((a, b) => a.firstname.localeCompare(b.firstname, 'es', {sensitivity: 'base'}))_x000D_
_x000D_
_x000D_
console.log(user)
_x000D_
_x000D_
_x000D_

The oficial locale options could be found here in iana, es (spanish), de (German), fr (French). About sensitivity base means:

Only strings that differ in base letters compare as unequal. Examples: a ? b, a = á, a = A.


Something like this:

array.sort(function(a, b){
 var nameA=a.name.toLowerCase(), nameB=b.name.toLowerCase();
 if (nameA < nameB) //sort string ascending
  return -1;
 if (nameA > nameB)
  return 1;
 return 0; //default return value (no sorting)
});