Sort array of objects by string property value

JavascriptArraysSortingComparison

Javascript Problem Overview


I have an array of JavaScript objects:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

How can I sort them by the value of last_nom in JavaScript?

I know about sort(a,b), but that only seems to work on strings and numbers. Do I need to add a toString() method to my objects?

Javascript Solutions


Solution 1 - Javascript

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

Solution 2 - Javascript

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");

[7]: https://github.com/zenparsing/es-function-bind "bind operator proposal" [8]: https://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice

Solution 3 - Javascript

In ES6/ES2015 or later you can do this way:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));

Prior to ES6/ES2015

objs.sort(function(a, b) {
	return a.last_nom.localeCompare(b.last_nom)
});

Solution 4 - Javascript

underscore.js

use underscore, its small and awesome...

> sortBy_.sortBy(list, iterator, [context]) Returns a sorted copy of > list, ranked in ascending order by the results of running each value > through iterator. Iterator may also be the string name of the property > to sort by (eg. length).

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' );

Solution 5 - Javascript

Case sensitive

arr.sort((a, b) => a.name > b.name ? 1 : -1);

Case Insensitive

arr.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1);

Useful Note

If no change in order (in case of the same strings) then the condition > will fail and -1 will be returned. But if strings are same then returning 1 or -1 will result in correct output

The other option could be to use >= operator instead of >


var objs = [     { first_nom: 'Lazslo', last_nom: 'Jamf'     },    { first_nom: 'Pig',    last_nom: 'Bodine'   },    { first_nom: 'Pirate', last_nom: 'Prentice' }];


// Define a couple of sorting callback functions, one with hardcoded sort key and the other with an argument sort key
const sorter1 = (a, b) => a.last_nom.toLowerCase() > b.last_nom.toLowerCase() ? 1 : -1;
const sorter2 = (sortBy) => (a, b) => a[sortBy].toLowerCase() > b[sortBy].toLowerCase() ? 1 : -1;

objs.sort(sorter1);
console.log("Using sorter1 - Hardcoded sort property last_name", objs);

objs.sort(sorter2('first_nom'));
console.log("Using sorter2 - passed param sortBy='first_nom'", objs);

objs.sort(sorter2('last_nom'));
console.log("Using sorter2 - passed param sortBy='last_nom'", objs);

Solution 6 - Javascript

If you have duplicate last names you might sort those by first name-

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

Solution 7 - Javascript

As of 2018 there is a much shorter and elegant solution. Just use. Array.prototype.sort().

Example:

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

Solution 8 - Javascript

Simple and quick solution to this problem using prototype inheritance:

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

Example / Usage

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"}]

Update: No longer modifies original array.

Solution 9 - Javascript

Old answer that is not correct:

arr.sort((a, b) => a.name > b.name)

UPDATE

From Beauchamp's comment:

arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))

More readable format:

arr.sort((a, b) => {
  if (a.name < b.name) return -1
  return a.name > b.name ? 1 : 0
})

Without nested ternaries:

arr.sort((a, b) => a.name < b.name ? - 1 : Number(a.name > b.name))

Explanation: Number() will cast true to 1 and false to 0.

Solution 10 - Javascript

Lodash.js (superset of Underscore.js)

It's good not to add a framework for every simple piece of logic, but relying on well tested utility frameworks can speed up development and reduce the amount of bugs.

Lodash produces very clean code and promotes a more functional programming style. In one glimpse it becomes clear what the intent of the code is.

OP's issue can simply be solved as:

const sortedObjs = _.sortBy(objs, 'last_nom');

More info? E.g. we have following nested object:

const users = [
  { 'user': {'name':'fred', 'age'48}},
  { 'user': {'name':'barney''age'36 }},
  { 'user': {'name':'wilma'}},
  { 'user': {'name':'betty', 'age'32}}
];

We now can use the _.property shorthand user.age to specify the path to the property that should be matched. We will sort the user objects by the nested age property. Yes, it allows for nested property matching!

const sortedObjs = _.sortBy(users, ['user.age']);

Want it reversed? No problem. Use _.reverse.

const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));

Want to combine both using chain?

const { chain } = require('lodash');
const sortedObjs = chain(users).sortBy('user.age').reverse().value();

Or when do you prefer flow over chain

const { flow, reverse, sortBy } = require('lodash/fp');
const sortedObjs = flow([sortBy('user.age'), reverse])(users); 

Solution 11 - Javascript

You can use Easiest Way: Lodash

(https://lodash.com/docs/4.17.10#orderBy)

This method is like _.sortBy except that it allows specifying the sort orders of the iteratees to sort by. If orders is unspecified, all values are sorted in ascending order. Otherwise, specify an order of "desc" for descending or "asc" for ascending sort order of corresponding values.

Arguments

collection (Array|Object): The collection to iterate over. [iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]): The iteratees to sort by. [orders] (string[]): The sort orders of iteratees.

Returns

(Array): Returns the new sorted array.


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']);

Solution 12 - Javascript

I haven't seen this particular approach suggested, so here's a terse comparison method I like to use that works for both string and number types:

const objs = [ 
  { first_nom: 'Lazslo', last_nom: 'Jamf'     },
  { first_nom: 'Pig',    last_nom: 'Bodine'   },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];

const sortBy = fn => {
  const cmp = (a, b) => -(a < b) || +(a > b);
  return (a, b) => cmp(fn(a), fn(b));
};

const getLastName = o => o.last_nom;
const sortByLastName = sortBy(getLastName);

objs.sort(sortByLastName);
console.log(objs.map(getLastName));

Explanation of sortBy()

sortBy() accepts a fn that selects a value from an object to use in comparison, and returns a function that can be passed to Array.prototype.sort(). In this example, we're comparing o.last_nom. Whenever we receive two objects such as

a = { first_nom: 'Lazslo', last_nom: 'Jamf' }
b = { first_nom: 'Pig', last_nom: 'Bodine' }

we compare them with (a, b) => cmp(fn(a), fn(b)). Given that

fn = o => o.last_nom

we can expand the comparison function to (a, b) => cmp(a.last_nom, b.last_nom). Because of the way logical OR (||) works in JavaScript, cmp(a.last_nom, b.last_nom) is equivalent to

if (a.last_nom < b.last_nom) return -1;
if (a.last_nom > b.last_nom) return 1;
return 0;

Incidentally, this is called the three-way comparison "spaceship" (<=>) operator in other languages.

Finally, here's the ES5-compatible syntax without using arrow functions:

var objs = [   { first_nom: 'Lazslo', last_nom: 'Jamf'     },  { first_nom: 'Pig',    last_nom: 'Bodine'   },  { first_nom: 'Pirate', last_nom: 'Prentice' }];

function sortBy(fn) {
  function cmp(a, b) { return -(a < b) || +(a > b); }
  return function (a, b) { return cmp(fn(a), fn(b)); };
}

function getLastName(o) { return o.last_nom; }
var sortByLastName = sortBy(getLastName);

objs.sort(sortByLastName);
console.log(objs.map(getLastName));

Solution 13 - Javascript

Instead of using a custom comparison function, you could also create an object type with custom toString() method (which is invoked by the default comparison function):

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();

Solution 14 - Javascript

There are many good answers here, but I would like to point out that they can be extended very simply to achieve a lot more complex sorting. The only thing you have to do is to use the OR operator to chain comparision functions like this:

objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )

Where fn1, fn2, ... are the sort functions which return [-1,0,1]. This results in "sorting by fn1", "sorting by fn2" which is pretty much equal to ORDER BY in SQL.

This solution is based on the behaviour of || operator which evaluates to the first evaluated expression which can be converted to true.

The simplest form has only one inlined function like this:

// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )

Having two steps with last_nom,first_nom sort order would look like this:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) || 
                  a.first_nom.localeCompare(b.first_nom)  )

A generic comparision function could be something like this:

// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])

This function could be extended to support numeric fields, case sensitity, arbitary datatypes etc.

You can them use it with chaining them by sort priority:

// 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") )

The point here is that pure JavaScript with functional approach can take you a long way without external libraries or complex code. It is also very effective, since no string parsing have to be done

Solution 15 - Javascript

Try this,

UPTO ES5

//Ascending Sort
items.sort(function (a, b) {
   return a.value - b.value;
});


//Descending Sort
items.sort(function (a, b) {
   return b.value - a.value;
});


IN ES6 & above:

// Ascending sort
items.sort((a, b) => a.value - b.value);

// Descending Sort
 items.sort((a, b) => b.value - a.value);

Solution 16 - Javascript

Example Usage:

objs.sort(sortBy('last_nom'));

Script:

/**
 * @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;
  };
};

Solution 17 - Javascript

I know this question is too old, but I didn't see any implementation similar to mine.
This version is based on the Schwartzian transform idiom.

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

Here's an example how to use it:

let games = [
  { name: 'Mashraki',          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'));

Solution 18 - Javascript

Why don't you write short code?

objs.sort((a, b) => a.last_nom > b.last_nom ? 1 : -1)

Solution 19 - Javascript

Sorting (more) Complex Arrays of Objects

Since you probably encounter more complex data structures like this array, I would expand the solution.

TL;DR

> Are more pluggable version based on @ege-Özcan's very lovely answer.

Problem

I encountered the below and couldn't change it. I also did not want to flatten the object temporarily. Nor did I want to use underscore / lodash, mainly for performance reasons and the fun to implement it myself.

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
Goal

The goal is to sort it primarily by People.Name.name and secondarily by People.Name.surname

Obstacles

Now, in the base solution uses bracket notation to compute the properties to sort for dynamically. Here, though, we would have to construct the bracket notation dynamically also, since you would expect some like People['Name.name'] would work - which doesn't.

Simply doing People['Name']['name'], on the other hand, is static and only allows you to go down the n-th level.

Solution

The main addition here will be to walk down the object tree and determine the value of the last leaf, you have to specify, as well as any intermediary leaf.

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

Example

Working example on JSBin

Solution 20 - Javascript

One more option:

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));

sorts ascending by default.

Solution 21 - Javascript

A simple way:

objs.sort(function(a,b) {
  return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});

See that '.toLowerCase()' is necessary to prevent erros in comparing strings.

Solution 22 - Javascript

> Warning!
Using this solution is not recommended as it does not result in a sorted array. It is being left here for future reference, because the idea is not rare.

objs.sort(function(a,b){return b.last_nom>a.last_nom})

Solution 23 - Javascript

This is my take on this:

The order parameter is optional and defaults to "ASC" for ascending order.

Works on accented chars and it's case insensitive.

NOTE: It sorts and returns the ORIGINAL array.

function sanitizeToSort(str) {
  return str
    .normalize('NFD')                   // REMOVE ACCENTED AND DIACRITICS
    .replace(/[\u0300-\u036f]/g,'')     // REMOVE ACCENTED AND DIACRITICS
    .toLowerCase()                      // SORT WILL BE CASE INSENSITIVE
  ;
}

function sortByProperty(arr, property, order="ASC") {
  arr.forEach((item) => item.tempProp = sanitizeToSort(item[property]));
  arr.sort((a,b) => order === "ASC" ?
      a.tempProp > b.tempProp ?  1 : a.tempProp < b.tempProp ? -1 : 0
    : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ?  1 : 0
  );
  arr.forEach((item) => delete item.tempProp);
  return arr;
}

SNIPPET

function sanitizeToSort(str) {
  return str
    .normalize('NFD')                   // REMOVE ACCENTED CHARS
    .replace(/[\u0300-\u036f]/g,'')     // REMOVE DIACRITICS
    .toLowerCase()
  ;
}

function sortByProperty(arr, property, order="ASC") {
  arr.forEach((item) => item.tempProp = sanitizeToSort(item[property]));
  arr.sort((a,b) => order === "ASC" ?
      a.tempProp > b.tempProp ?  1 : a.tempProp < b.tempProp ? -1 : 0
    : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ?  1 : 0
  );
  arr.forEach((item) => delete item.tempProp);
  return arr;
}

const rockStars = [
  { name: "Axl",
    lastname: "Rose" },
  { name: "Elthon",
    lastname: "John" },
  { name: "Paul",
    lastname: "McCartney" },
  { name: "Lou",
    lastname: "Reed" },
  { name: "freddie",             // WORKS ON LOWER/UPPER CASE
    lastname: "mercury" },
  { name: "Ámy",                 // WORKS ON ACCENTED CHARS TOO
    lastname: "winehouse"}
  
];

sortByProperty(rockStars,"name");

console.log("Ordered by name A-Z:");
rockStars.forEach((item) => console.log(item.name + " " + item.lastname));

sortByProperty(rockStars,"lastname","DESC");

console.log("\nOrdered by lastname Z-A:");
rockStars.forEach((item) => console.log(item.lastname + ", " + item.name));

Solution 24 - Javascript

Use JavaScript sort method

The sort method can be modified to sort anything like an array of numbers, strings and even objects using a compare function.

A compare function is passed as an optional argument to the sort method.

This compare function accepts 2 arguments generally called a and b. Based on these 2 arguments you can modify the sort method to work as you want.

  1. If the compare function returns less than 0, then the sort() method sorts a at a lower index than b. Simply a will come before b.
  2. If the compare function returns equal to 0, then the sort() method leaves the element positions as they are.
  3. If the compare function returns greater than 0, then the sort() method sorts a at greater index than b. Simply a will come after b.

Use the above concept to apply on your object where a will be your object property.

var objs = [
  { first_nom: 'Lazslo', last_nom: 'Jamf' },
  { first_nom: 'Pig', last_nom: 'Bodine' },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];
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);
console.log(objs)
// for better look use console.table(objs)

output

Solution 25 - Javascript

additional desc params for Ege Özcan code

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

Solution 26 - Javascript

Given the original example:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

Sort by multiple fields:

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

Notes

  • a.localeCompare(b) is universally supported and returns -1,0,1 if a<b,a==b,a>b respectively.
  • || in the last line gives last_nom priority over first_nom.
  • Subtraction works on numeric fields: var age_order = left.age - right.age;
  • Negate to reverse order, return -last_nom_order || -first_nom_order || -age_order;

Solution 27 - Javascript

A simple function that sort an array of object by a property

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
}

Usage:

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

Solution 28 - Javascript

Combining Ege's dynamic solution with Vinay's idea, you get a nice robust solution:

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

Usage:

// 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");

Solution 29 - Javascript

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"));

Solution 30 - Javascript

Using Ramda,

npm install 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)

Solution 31 - Javascript

You can use a reusable sort function.

Array.prototype.order = function (prop, methods = {}) {
    if (prop?.constructor == Object) {
        methods = prop;
        prop = null;
    }
    const [orderType_a, orderType_b] = methods.reverse ? [1, -1] : [-1, 1];

    const $ = x => prop
        ? methods.insensitive
            ? String(x[prop]).toLowerCase()
            : x[prop]
        : methods.insensitive
            ? String(x).toLowerCase()
            : x;

    const fn = (a, b) => $(a) < $(b) ? orderType_a : $(b) < $(a) ? orderType_b : 0;
    return this.sort(fn);
};

Its can be use to sort both Array and Object in array
.

let items = [{ x: "Z" }, 3, "1", "0", 2, { x: "a" }, { x: 0 }];
items
    .order("x", { insensitive: 1 })
    // [ { x: 0 }, { x: 'a' }, 3, '1', '0', 2, { x: 'Z' } ]
    .order({ reverse: 1 })
    // [ { x: 0 }, { x: 'a' }, 3, 2, { x: 'Z' }, '1', '0' ]
    .sort(x => typeof x == "string" || typeof x == "number" ? -1 : 0)
    // [ '0', '1', 2, 3, { x: 0 }, { x: 'a' }, { x: 'Z' } ]

1nd (optional) > to sort object contain in array.
2rd is method > { reverse: any, insensitive: any }

Solution 32 - Javascript

Acording your example, you need to sort by two fields (last name, first name), rather then one. You can use Alasql library to make this sort in one line:

var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);

Try this example at jsFiddle.

Solution 33 - Javascript

This is a simple problem, don't know why people have such complex solution.
A simple sort function (based on quick-sort algorithm):

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

Use example:

var myArr = 
        [
            { val: 'x', idx: 3 },
            { val: 'y', idx: 2 },
            { val: 'z', idx: 5 },
        ];
myArr = sortObjectsArray(myArr, 'idx');

Solution 34 - Javascript

You may need to convert them to the lower case in order to prevent from confusion.

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

})

Solution 35 - Javascript

Way 1 :

You can use Underscore.js. Import underscore first.

 import * as _ from 'underscore';
 let SortedObjs = _.sortBy(objs, 'last_nom');

Way 2 : Use compare function.

function compare(first, second) {
     if (first.last_nom < second.last_nom)
         return -1;
     if (first.last_nom > second.last_nom)
       return 1;
    return 0;
 }

objs.sort(compare);

Solution 36 - Javascript

Simple answer:

objs.sort((a,b)=>a.last_nom.localeCompare(b.last_nom))

Details:

Today it is very simple, You can compare strings with localeCompare. As the Mozilla Doc says:

> The localeCompare() method returns a number indicating whether a > reference string comes before, or after, or is the same as the > given string in sort order.

    //example1:
    console.log("aaa".localeCompare("aab")); //-1
    console.log("aaa".localeCompare("aaa")); //0
    console.log("aab".localeCompare("aaa")); //1

    //example2:
    const a = 'réservé'; // with accents, lowercase
    const b = 'RESERVE'; // no accents, uppercase

    console.log(a.localeCompare(b));
    // expected output: 1
    console.log(a.localeCompare(b, 'en', { sensitivity: 'base' }));
    // expected output: 0

For more details see Mozilla doclocaleCompare:

Solution 37 - Javascript

> It works for me. Here It will keep undefined to the end.

 function sort(items, property, direction) {

    function compare(a, b) {
      if(!a[property] && !b[property]) {
        return 0;
      } else if(a[property] && !b[property]) {
        return -1;
      } else if(!a[property] && b[property]) {
        return 1;
      } else {
        const value1 = a[property].toString().toUpperCase(); // ignore upper and lowercase
        const value2 = b[property].toString().toUpperCase(); // ignore upper and lowercase
        if (value1 < value2) {
          return direction === 0 ? -1 : 1;
        } else if (value1 > value2) {
          return direction === 0 ? 1 : -1;
        } else {
          return 0;
        }
        
      }
    }
    
    return items.sort(compare);
   } 
   
   var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: undefined, value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];
   console.log('Ascending Order:- ');
   console.log(sort(items, 'name', 0));
   console.log('Decending Order:- ');
   console.log(sort(items, 'name', 1));
    
    

Solution 38 - Javascript

Using 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"}
*/

Solution 39 - Javascript

I Just enhanced Ege Özcan's dynamic sort to dive deep inside objects. If Data looks like this:

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

and if you want to sort it over a.a property I think my enhancement helps very well. I add new functionality to objects like this:

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

and changed _dynamicSort's return function:

return function (a,b) {
		var result = ((a.deepVal(property) > b.deepVal(property)) - (a.deepVal(property) < b.deepVal(property)));
		return result * sortOrder;
	}

And now you can sort by a.a. this way:

obj.sortBy('a.a');

See Commplete script in JSFiddle

Solution 40 - Javascript

Using lodash or Underscore, its a piece of cake

> const sortedList = _.orderBy(objs, [last_nom], [asc]); // asc or desc

Solution 41 - Javascript

It is also possible to make a dynamic sorting function when programming in TypeScript, but the types become more tricky in this case.

function sortByKey<O>(key: keyof O, decending: boolean = false): (a: O, b: O) => number {
	const order = decending ? -1 : 1;
	return (a, b): number => {
		const valA = a[key];
		const valB = b[key];
		if (valA < valB) {
			return -order;
		} else if (valA > valB) {
			return order;
		} else {
			return 0;
		}
	}
}

This can be used in TypeScript as the following:

const test = [
	{
		id: 0,
	},
	{
		id: 2,
	}
]

test.sort(sortByKey('id')) // OK
test.sort(sortByKey('id1')) // ERROR
test.sort(sortByKey('')) // ERROR

Solution 42 - Javascript

this sorting funciton can be use for all object sorting,

  • object

  • deepObject

  • numeric array

you can also do assending or desending sort by passing 1,-1 as param

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


function dynamicSortAll(property,sortOrders=1) {

/default sorting will be ascending order if you need descending order sording you have to pass -1 as param/

    var sortOrder = sortOrders;
   
    return function (a,b) {

		 var result =(property? ((a.deepVal(property) > b.deepVal(property)) ? 1 : (a.deepVal(property) < b.deepVal(property)) ? -1 : 0) :((a > b) ? 1 : (a < b) ? -1 : 0))
		
        return result * sortOrder;
		
   
    }
}

deepObj = [
    {
        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 }
}];

let deepobjResult=deepObj.sort(dynamicSortAll('a.a',1))
console.log('deepobjResult :'+ JSON.stringify(deepobjResult))
var obj = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];
let objResult=obj.sort(dynamicSortAll('last_nom',1))
console.log('objResult :'+ JSON.stringify(objResult))

var numericObj=[1,2,3,4,5,6]

let numResult=numericObj.sort(dynamicSortAll(null,-1))
console.log('numResult :'+ JSON.stringify(numResult))

let stringSortResult='helloworld'.split('').sort(dynamicSortAll(null,1))

console.log('stringSortResult:'+ JSON.stringify(stringSortResult))

let uniqueStringOrger=[...new Set(stringSortResult)]; console.log('uniqueStringOrger:'+ JSON.stringify(uniqueStringOrger))

Solution 43 - Javascript

Deep

Based on this excellent tutorial I would like to develop Vlad Bezden answer and explain why localeCompare is better than standard comarison method like strA > strB. Lets run this example

console.log( 'Österreich' > 'Zealand' );  // We expect false
console.log( 'a' > 'Z' );                 // We expect false

The reason is that in JS all strings are encoded using UTF-16 and

let str = '';

// order of characters in JS
for (let i = 65; i <= 220; i++) {
  str += String.fromCodePoint(i); // code to character
}

console.log(str);

Capital letters go first (have small codes) and then go small letters and then go character Ö (after z). This is reason why we get true in first snippet - becasue operator > compare characters codes.

As you can see compare characters in diffrent languages is non trivial task - but luckily, modern browsers support the internationalization standard ECMA-402. So in JS we have strA.localeCompare(strB) which do the job (-1 means strA is less than strB; 1 means opposite; 0 means equal)

console.log( 'Österreich'.localeCompare('Zealand') ); // We expect -1
console.log( 'a'.localeCompare('Z') );                // We expect -1

I would like to add that localeCompare supports two parameters: language and additional rules

var objs = [     { first_nom: 'Lazslo', last_nom: 'Jamf'     },    { first_nom: 'Pig',    last_nom: 'Bodine'   },    { first_nom: 'Pirate', last_nom: 'Prentice' },    { first_nom: 'Test',   last_nom: 'jamf'     } ];

objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom,'en',{sensitivity:'case'}))

console.log(objs);

// in '>' comparison 'Jamf' will NOT be next to 'jamf'

Solution 44 - Javascript

I've been using this utility in a variety of projects and it works great. It's very modular too:

  • Pass the name of the key to sort by
  • Choose if the sorting is ascending or descending

sortArrayOfObjsByKeyUtil.js

// Sort array of objects by key
// ------------------------------------------------------------
const sortArrayOfObjsByKey = (array, key, ascdesc) =>
  array.sort((a, b) => {
    const x = a[key];
    const y = b[key];
    if (ascdesc === 'asc') {
      return x < y ? -1 : x > y ? 1 : 0;
    }
    if (ascdesc === 'desc') {
      return x > y ? -1 : x < y ? 1 : 0;
    }
    return null;
  });

sortArrayOfObjsByKeyUtil.test.js

import sortArrayOfObjsByKey from './sortArrayOfObjsByKeyUtil';

const unsortedArray = [
  {
    _id: '3df55221-ce5c-4147-8e14-32effede6133',
    title: 'Netlife Design',
    address: {
      PostalAddress: {
        streetAddress: 'Youngstorget 3',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0181',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.914322, lng: 10.749272 },
  },
  {
    _id: 'cd00459f-3755-49f1-8847-66591ef935b2',
    title: 'Home',
    address: {
      PostalAddress: {
        streetAddress: 'Stockfleths gate 58A',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0461',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.937316, lng: 10.751862 },
  },
];

const sortedArray = [
  {
    _id: 'cd00459f-3755-49f1-8847-66591ef935b2',
    title: 'Home',
    address: {
      PostalAddress: {
        streetAddress: 'Stockfleths gate 58A',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0461',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.937316, lng: 10.751862 },
  },
  {
    _id: '3df55221-ce5c-4147-8e14-32effede6133',
    title: 'Netlife Design',
    address: {
      PostalAddress: {
        streetAddress: 'Youngstorget 3',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0181',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.914322, lng: 10.749272 },
  },
];

describe('sortArrayOfObjsByKey', () => {
  it(`sort array by 'title' key, ascending`, () => {
    const testInput = sortArrayOfObjsByKey(unsortedArray, 'title', 'asc');
    const testOutput = sortedArray;
    expect(testInput).toEqual(testOutput);
  });
});

Solution 45 - Javascript

Sorting objects with Intl.Collator for the specific case when you want natural sorting (i.e. 1,2,10,11,111).

const files = [
 {name: "1.mp3", size: 123},
 {name: "10.mp3", size: 456},
 {name: "100.mp3", size: 789},
 {name: "11.mp3", size: 123},
 {name: "111.mp3", size: 456},
 {name: "2.mp3", size: 789},
];

const naturalCollator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});

files.sort((a, b) => naturalCollator.compare(a.name, b.name));

console.log(files);

Browser support for Intl.Collator

Solution 46 - Javascript

I came into problem of sorting array of objects, with changing priority of values, basically I want to sort array of peoples by their Age, and then by surname - or just by surname, name. I think that this is most simple solution compared to another answers.

it' is used by calling sortPeoples(['array', 'of', 'properties'], reverse=false)

///////////////////////example array of peoples ///////////////////////

var peoples = [
    {name: "Zach", surname: "Emergency", age: 1},
    {name: "Nancy", surname: "Nurse", age: 1},
    {name: "Ethel", surname: "Emergency", age: 1},
    {name: "Nina", surname: "Nurse", age: 42},
    {name: "Anthony", surname: "Emergency", age: 42},
    {name: "Nina", surname: "Nurse", age: 32},
    {name: "Ed", surname: "Emergency", age: 28},
    {name: "Peter", surname: "Physician", age: 58},
    {name: "Al", surname: "Emergency", age: 58},
    {name: "Ruth", surname: "Registration", age: 62},
    {name: "Ed", surname: "Emergency", age: 38},
    {name: "Tammy", surname: "Triage", age: 29},
    {name: "Alan", surname: "Emergency", age: 60},
    {name: "Nina", surname: "Nurse", age: 58}
];



//////////////////////// Sorting function /////////////////////
function sortPeoples(propertyArr, reverse) {
        function compare(a,b) {
            var i=0;
            while (propertyArr[i]) {
                if (a[propertyArr[i]] < b[propertyArr[i]])  return -1;
                if (a[propertyArr[i]] > b[propertyArr[i]])  return 1;
                i++;
            }
            return 0;
            }
        peoples.sort(compare);
        if (reverse){
            peoples.reverse();
        }
    };

////////////////end of sorting method///////////////
function printPeoples(){
  $('#output').html('');
peoples.forEach( function(person){
 $('#output').append(person.surname+" "+person.name+" "+person.age+"<br>");
} )
}

<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
  <html>
  <body>
<button onclick="sortPeoples(['surname']); printPeoples()">sort by ONLY by surname ASC results in mess with same name cases</button><br>
<button onclick="sortPeoples(['surname', 'name'], true); printPeoples()">sort by surname then name DESC</button><br>
<button onclick="sortPeoples(['age']); printPeoples()">sort by AGE ASC. Same issue as in first case</button><br>
<button onclick="sortPeoples(['age', 'surname']); printPeoples()">sort by AGE and Surname ASC. Adding second field fixed it.</button><br>
        
    <div id="output"></div>
    </body>
  </html>

Solution 47 - Javascript

// Sort Array of Objects

// Data
var booksArray = [
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

// Property to Sort By
var args = "last_nom";

// Function to Sort the Data by given Property
function sortByProperty(property) {
    return function (a, b) {
        var sortStatus = 0,
            aProp = a[property].toLowerCase(),
            bProp = b[property].toLowerCase();
        if (aProp < bProp) {
            sortStatus = -1;
        } else if (aProp > bProp) {
            sortStatus = 1;
        }
        return sortStatus;
    };
}

// Implementation
var sortedArray = booksArray.sort(sortByProperty(args));

console.log("sortedArray: " + JSON.stringify(sortedArray) );

Console log output:

"sortedArray: 
[{"first_nom":"Pig","last_nom":"Bodine"},
{"first_nom":"Lazslo","last_nom":"Jamf"},
{"first_nom":"Pirate","last_nom":"Prentice"}]"

Adapted based on this source: https://web.archive.org/web/20210515081841/http://opnsrce.github.io/code-snippet-how-to-sort-an-array-of-json-objects-by-property

Solution 48 - Javascript

This will sort a two level nested array by the property passed to it in alpha numeric order.

function sortArrayObjectsByPropAlphaNum(property) {
	return function (a,b) {
		var reA = /[^a-zA-Z]/g;
		var reN = /[^0-9]/g;
		var aA = a[property].replace(reA, '');
		var bA = b[property].replace(reA, '');

		if(aA === bA) {
			var aN = parseInt(a[property].replace(reN, ''), 10);
			var bN = parseInt(b[property].replace(reN, ''), 10);
			return aN === bN ? 0 : aN > bN ? 1 : -1;
		} else {
			return a[property] > b[property] ? 1 : -1;
		}
	};
}

Usage:

objs.sort(utils.sortArrayObjectsByPropAlphaNum('last_nom'));

Solution 49 - Javascript

So here is one sorting algorithm which can sort in any order , throughout array of any kind of objects , without the restriction of datatype comparison ( i.e. Number , String )

function smoothSort(items,prop,reverse) {  
    var length = items.length;
    for (var i = (length - 1); i >= 0; i--) {
        //Number of passes
        for (var j = (length - i); j > 0; j--) {
            //Compare the adjacent positions
            if(reverse){
              if (items[j][prop] > items[j - 1][prop]) {
                //Swap the numbers
                var tmp = items[j];
                items[j] = items[j - 1];
                items[j - 1] = tmp;
            }
            }
            
            if(!reverse){
              if (items[j][prop] < items[j - 1][prop]) {
                  //Swap the numbers
                  var tmp = items[j];
                  items[j] = items[j - 1];
                  items[j - 1] = tmp;
              }
            }
        }
    }

    return items;
}
  • the first argument items is the array of objects ,

  • prop is the key of the object on which you want to sort ,

  • reverse is a boolean parameter which on being true results in Ascending order and in false it returns descending order.

Solution 50 - Javascript

Hers a function you can use to sort the list by multiple objects, where if the first object is equal, the second order will be used as a fallback. empty values should also be ignored to fallback order if possible.

function sortObjects(list, orderBy){
	list.sort(function(a, b){
		let byIndex = 0;
		let order = orderBy[byIndex];
		while(!a[order.by] || !b[order.by] || a[order.by] === b[order.by]){
		    byIndex++;
		    if(byIndex >= orderBy.length){break;}
		    order = orderBy[byIndex];
	    }
        if(!a[order.by] || !b[order.by] || a[order.by] === b[order.by]){
		    return false;
	    }
		if(order.desc){
			return a[order.by] < b[order.by];
		}
		return a[order.by] > b[order.by];
	});
	return list;
}

usage:

var objs = [
    {a: 10, b: 20, c: 30},
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
];

sortObjectList(objs, [{by: 'a'}]);
[
    {a: 10, b: 20, c: 30},
    {a: 20, b: 10, c: 30},
    {a: 30, b: 10, c: 20},
]

sortObjectList(objs, [{by: 'a', desc: true}]);
[
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
    {a: 10, b: 20, c: 30},
]

sortObjectList(objs, [{by: 'b', desc: true}, {by: 'c'}]);
[
    {a: 10, b: 20, c: 30},
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
]

another example:

var objs = [
	{a: 5, b: 5},
	{a: 10, b: 15},
	{a: 15, b: 25},
	{b: 10},
	{b: 20},
	{a: 10, b: 30},
    {a: 10, b: 12},
];

sortObjectList(objs, [{by: 'a'}, {by: 'b'}]);
[
    {a: 5, b: 5},
    {b: 10},
    {a: 10, b: 12},
    {a: 10, b: 15},
    {b: 20},
    {a: 10, b: 30},
    {a: 15, b: 25},
]

Solution 51 - Javascript

For fp-holics:

const objectSorter = (p)=>(a,b)=>((a,b)=>a>b?1:a<b?-1:0)(a[p], b[p]);
objs.sort(objectSorter('first_nom'));

Solution 52 - Javascript

I will give you a solution implementing selectionSort algorithm ,it is simple and effective

var objs = [ 
{ first_nom: 'Lazslo', last_nom: 'Jamf'     },
{ first_nom: 'Pig',    last_nom: 'Bodine'   },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];


function selection_Sort(num) { 
 //console.log(num);  
 var temp, index;
 for (var i = 0; i <= num.length - 1; i++) {
index = i;
for (var j = i + 1; j <= num.length - 1; j++) {
 // you can use first_nom/last_nom,any way you choose to sort

  if (num[j]. last_nom < num[index]. last_nom) {
    index = j;
  } 
}

//below is the swapping part
temp = num[i]. last_nom;
num[i]. last_nom = num[index]. last_nom;
num[index]. last_nom = temp;
 };
 console.log(num); 
 return num; 
  }
  selection_Sort(objs);

Great to see such great answers

Solution 53 - Javascript

In case you have nested objects

const objs = [{
        first_nom: 'Lazslo',
        last_nom: 'Jamf',
        moreDetails: {
            age: 20
        }
    }, {
        first_nom: 'Pig',
        last_nom: 'Bodine',
        moreDetails: {
            age: 21
        }
    }, {
        first_nom: 'Pirate',
        last_nom: 'Prentice',
        moreDetails: {
            age: 22
        }
    }];

nestedSort = (prop1, prop2 = null, direction = 'asc') => (e1, e2) => {
        const a = prop2 ? e1[prop1][prop2] : e1[prop1],
            b = prop2 ? e2[prop1][prop2] : e2[prop1],
            sortOrder = direction === "asc" ? 1 : -1
        return (a < b) ? -sortOrder : (a > b) ? sortOrder : 0;
    }

and call it like

objs.sort(nestedSort("last_nom"));
objs.sort(nestedSort("last_nom", null, "desc"));
objs.sort(nestedSort("moreDetails", "age"));
objs.sort(nestedSort("moreDetails", "age", "desc"));

Solution 54 - Javascript

//Try this way


let objs = [ 
        { first_nom: 'Lazslo', last_nom: 'Jamf'     },
        { first_nom: 'Pig',    last_nom: 'Bodine'   },
        { first_nom: 'Pirate', last_nom: 'Prentice' }
    ];
    const compareBylastNom = (a, b) => {
        // converting to uppercase to have case-insensitive comparison
        const name1 = a.last_nom.toUpperCase();
        const name2 = b.last_nom.toUpperCase();
    
        let comparison = 0;
    
        if (name1 > name2) {
            comparison = 1;
        } else if (name1 < name2) {
            comparison = -1;
        }
        return comparison;
    }
    console.log(objs.sort(compareBylastNom));

Solution 55 - Javascript

I know there is already plenty of answers, including those with localeCompare ones, but if you don't want to/can't use localeCompare for some reason, I would suggest you to use this solution instead of ternary operator solution:

objects.sort((a, b) => (a.name > b.name) - (a.name < b.name));

Someone could say that it's not obvious what this code is doing, but in my opinion ternary operator is worse. If one ternary operator is readable enough, two ternary operators one embedded into another — really hard to read and ugly. One-line code with just two comparison operators and one minus operator is very simple to read and thus to reason.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTyrone SlothropView Question on Stackoverflow
Solution 1 - JavascriptWoganView Answer on Stackoverflow
Solution 2 - JavascriptEge ÖzcanView Answer on Stackoverflow
Solution 3 - JavascriptVlad BezdenView Answer on Stackoverflow
Solution 4 - JavascriptDavid MorrowView Answer on Stackoverflow
Solution 5 - Javascriptmuasif80View Answer on Stackoverflow
Solution 6 - JavascriptkennebecView Answer on Stackoverflow
Solution 7 - Javascript0legView Answer on Stackoverflow
Solution 8 - JavascriptVinay AggarwalView Answer on Stackoverflow
Solution 9 - JavascriptDamian PavlicaView Answer on Stackoverflow
Solution 10 - JavascriptNico Van BelleView Answer on Stackoverflow
Solution 11 - JavascriptHarshal Y.View Answer on Stackoverflow
Solution 12 - JavascriptPatrick RobertsView Answer on Stackoverflow
Solution 13 - JavascriptChristophView Answer on Stackoverflow
Solution 14 - JavascriptTero TolonenView Answer on Stackoverflow
Solution 15 - JavascriptAbhishekView Answer on Stackoverflow
Solution 16 - JavascriptJamie MasonView Answer on Stackoverflow
Solution 17 - Javascripta8mView Answer on Stackoverflow
Solution 18 - JavascriptartemView Answer on Stackoverflow
Solution 19 - JavascripteljefedelrodeodeljefeView Answer on Stackoverflow
Solution 20 - JavascriptravshansboxView Answer on Stackoverflow
Solution 21 - JavascriptCaio LadislauView Answer on Stackoverflow
Solution 22 - JavascriptRoshni BokadeView Answer on Stackoverflow
Solution 23 - JavascriptcbdeveloperView Answer on Stackoverflow
Solution 24 - JavascriptSatish Chandra GuptaView Answer on Stackoverflow
Solution 25 - JavascriptBehnam ShomaliView Answer on Stackoverflow
Solution 26 - JavascriptBob SteinView Answer on Stackoverflow
Solution 27 - JavascriptFrancois GirardView Answer on Stackoverflow
Solution 28 - JavascriptMike RView Answer on Stackoverflow
Solution 29 - JavascriptEvgeniiView Answer on Stackoverflow
Solution 30 - JavascriptSridhar SgView Answer on Stackoverflow
Solution 31 - JavascriptNurView Answer on Stackoverflow
Solution 32 - JavascriptagershunView Answer on Stackoverflow
Solution 33 - JavascriptGil EpshtainView Answer on Stackoverflow
Solution 34 - JavascriptBurak KeceliView Answer on Stackoverflow
Solution 35 - JavascriptHarun Or RashidView Answer on Stackoverflow
Solution 36 - JavascriptSeyyedKhandonView Answer on Stackoverflow
Solution 37 - Javascriptchandan guptaView Answer on Stackoverflow
Solution 38 - JavascriptEduardo CuomoView Answer on Stackoverflow
Solution 39 - JavascriptMorteza TouraniView Answer on Stackoverflow
Solution 40 - Javascriptkarthik006View Answer on Stackoverflow
Solution 41 - JavascriptFerrybigView Answer on Stackoverflow
Solution 42 - JavascriptJadliView Answer on Stackoverflow
Solution 43 - JavascriptKamil KiełczewskiView Answer on Stackoverflow
Solution 44 - JavascriptWallace SidhréeView Answer on Stackoverflow
Solution 45 - JavascriptccpizzaView Answer on Stackoverflow
Solution 46 - JavascriptjmwierzbickiView Answer on Stackoverflow
Solution 47 - JavascriptLuke SchoenView Answer on Stackoverflow
Solution 48 - JavascriptdepictionView Answer on Stackoverflow
Solution 49 - JavascriptPartha RoyView Answer on Stackoverflow
Solution 50 - JavascriptSwiftNinjaProView Answer on Stackoverflow
Solution 51 - JavascriptMarinos AnView Answer on Stackoverflow
Solution 52 - Javascriptsg28View Answer on Stackoverflow
Solution 53 - JavascriptMasView Answer on Stackoverflow
Solution 54 - JavascriptForce BoltView Answer on Stackoverflow
Solution 55 - JavascriptRustamView Answer on Stackoverflow