By TomHankers


2009-06-11 03:59:54 8 Comments

I read the following objects using Ajax and stored them in an array:

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": "5",
        "city": "New York",
        "state": "NY",
        "zip": "00010",
        "price": "962500"
    }
];

How do I create a function to sort the objects by the price property in ascending or descending order using only JavaScript?

27 comments

@Arushi Bajpai 2019-06-14 08:18:37

Descending order of price:

homes.sort((x,y) => {return y.price - x.price})

Ascending order of price:

homes.sort((x,y) => {return x.price - y.price})

@Nils 2019-06-25 18:06:18

Thats exactly the same code for both cases...

@Arushi Bajpai 2019-07-03 06:39:59

Sorry, Let me correct that small mistake. :)

@Andrew Rayan 2019-03-10 14:45:20

Create a function and sort based on the input using below code

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": "5",
    "city": "New York",
    "state": "NY",
    "zip": "00010",
    "price": "962500"

 }];

 function sortList(list,order){
     if(order=="ASC"){
        return list.sort((a,b)=>{
            return parseFloat(a.price) - parseFloat(b.price);
        })
     }
     else{
        return list.sort((a,b)=>{
            return parseFloat(b.price) - parseFloat(a.price);
        });
     }
 }

 sortList(homes,'DESC');
 console.log(homes);

@Santosh 2019-01-24 12:26:53

I'm little late for the party but below is my logic for sorting.

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

@Mitchell Skurnik 2018-06-01 23:44:39

While I am aware that the OP wanted to sort an array of numbers, this question has been marked as the answer for similar questions regarding strings. To that fact, the above answers do not consider sorting an array of text where casing is important. Most answers take the string values and convert them to uppercase/lowercase and then sort one way or another. The requirements that I adhere to are simple:

  • Sort alphabetically A-Z
  • Uppercase values of the same word should come before lowercase values
  • Same letter (A/a, B/b) values should be grouped together

What I expect is [ A, a, B, b, C, c ] but the answers above return A, B, C, a, b, c. I actually scratched my head on this for longer than I wanted (which is why I am posting this in hopes that it will help at least one other person). While two users mention the localeCompare function in the comments for the marked answer, I didn't see that until after I stumbled upon the function while searching around. After reading the String.prototype.localeCompare() documentation I was able to come up with this:

var values = [ "Delta", "charlie", "delta", "Charlie", "Bravo", "alpha", "Alpha", "bravo" ];
var sorted = values.sort((a, b) => a.localeCompare(b, undefined, { caseFirst: "upper" }));
// Result: [ "Alpha", "alpha", "Bravo", "bravo", "Charlie", "charlie", "Delta", "delta" ]

This tells the function to sort uppercase values before lowercase values. The second parameter in the localeCompare function is to define the locale but if you leave it as undefined it automatically figures out the locale for you.

This works the same for sorting an array of objects as well:

var values = [
    { id: 6, title: "Delta" },
    { id: 2, title: "charlie" },
    { id: 3, title: "delta" },
    { id: 1, title: "Charlie" },
    { id: 8, title: "Bravo" },
    { id: 5, title: "alpha" },
    { id: 4, title: "Alpha" },
    { id: 7, title: "bravo" }
];
var sorted = values
    .sort((a, b) => a.title.localeCompare(b.title, undefined, { caseFirst: "upper" }));

@Stephen Quan 2016-11-25 01:02:06

If you have an ES6 compliant browser you can use:

The difference between ascending and descending sort order is the sign of the value returned by your compare function:

var ascending = homes.sort((a, b) => Number(a.price) - Number(b.price));
var descending = homes.sort((a, b) => Number(b.price) - Number(a.price));

Here's a working code snippet:

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": "5",
  "city": "New York",
  "state": "NY",
  "zip": "00010",
  "price": "962500"
}];

homes.sort((a, b) => Number(a.price) - Number(b.price));
console.log("ascending", homes);

homes.sort((a, b) => Number(b.price) - Number(a.price));
console.log("descending", homes);

@HynekS 2018-05-28 20:40:53

It returns the same array both for the descending and the ascending function. I smell a bug there.

@Stephen Quan 2018-05-29 00:40:16

Thanks for your comment, @Hynek. I've amended the sample to show the sort() function modifies the original array.

@jherax 2014-11-05 16:28:36

I recommend GitHub: Array sortBy - a best implementation of sortBy method which uses the Schwartzian transform

But for now we are going to try this approach Gist: sortBy-old.js.
Let's create a method to sort arrays being able to arrange objects by some property.

Creating the sorting function

var sortBy = (function () {
  var toString = Object.prototype.toString,
      // default parser function
      parse = function (x) { return x; },
      // gets the item to be sorted
      getItem = function (x) {
        var isObject = x != null && typeof x === "object";
        var isProp = isObject && this.prop in x;
        return this.parser(isProp ? x[this.prop] : x);
      };

  /**
   * Sorts an array of elements.
   *
   * @param  {Array} array: the collection to sort
   * @param  {Object} cfg: the configuration options
   * @property {String}   cfg.prop: property name (if it is an Array of objects)
   * @property {Boolean}  cfg.desc: determines whether the sort is descending
   * @property {Function} cfg.parser: function to parse the items to expected type
   * @return {Array}
   */
  return function sortby (array, cfg) {
    if (!(array instanceof Array && array.length)) return [];
    if (toString.call(cfg) !== "[object Object]") cfg = {};
    if (typeof cfg.parser !== "function") cfg.parser = parse;
    cfg.desc = !!cfg.desc ? -1 : 1;
    return array.sort(function (a, b) {
      a = getItem.call(cfg, a);
      b = getItem.call(cfg, b);
      return cfg.desc * (a < b ? -1 : +(a > b));
    });
  };

}());

Setting unsorted data

var data = [
  {date: "2011-11-14T16:30:43Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:22:59Z", quantity: 2, total: 90,  tip: 0,   type: "Tab"},
  {date: "2011-11-14T16:28:54Z", quantity: 1, total: 300, tip: 200, type: "visa"},
  {date: "2011-11-14T16:53:41Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:48:46Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:25:45Z", quantity: 2, total: 200, tip: 0,   type: "cash"},
  {date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"},
  {date: "2011-11-14T16:58:03Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:20:19Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-14T17:07:21Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0,   type: "Cash"}
];

Using it

Arrange the array, by "date" as String

// sort by @date (ascending)
sortBy(data, { prop: "date" });

// expected: first element
// { date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab" }

// expected: last element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"}

If you want to ignore case sensitive, set the parser callback:

// sort by @type (ascending) IGNORING case-sensitive
sortBy(data, {
    prop: "type",
    parser: (t) => t.toUpperCase()
});

// expected: first element
// { date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0, type: "Cash" }

// expected: last element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa" }

If you want to convert the "date" field as Date type:

// sort by @date (descending) AS Date object
sortBy(data, {
    prop: "date",
    desc: true,
    parser: (d) => new Date(d)
});

// expected: first element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"}

// expected: last element
// { date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab" }

Here you can play with the code: jsbin.com/lesebi

Thanks to @Ozesh by his feedback, the issue related to properties with falsy values was fixed.

@jherax 2016-04-11 04:07:48

I added a new and more powerful implementation, allowing multiple sort, e.g. field1 ASC, after field2 DESC, after field3 DESC. The new sortBy method is an implementation of Schwartzian transform and you can find it here: gist: sortBy.js

@TSNev 2016-08-25 13:51:11

This seems to breaks when a field is null.

@jherax 2016-08-25 17:11:36

@TSNev could you please provide an example (jsfiddle, plunkr, etc)? I tried to replicate it with no success, null values were ordered at the end of array.

@Ozesh 2016-10-20 04:29:49

In case you are sorting through numbers and you encounter a '0' in between the array of objects, you might notice that the above code breaks.. Here is a quick fix for that : var checkNaN = function (value) { return Number.isNaN(Number(value)) ? 0 : value; } followed by: return function (array, o) { .... a = _getItem.call(o, a); a = checkNaN(a); b = _getItem.call(o, b); b = checkNaN(b); return o.desc * (a < b ? -1 : +(a > b)); });

@jherax 2016-10-20 04:43:20

Thank you for your feedback @Ozesh, the sortBy version above is deprecated :) I have written a new and more powerful implementation for sorting arrays. Check this gist: sortBy

@jherax 2016-10-20 05:40:51

@Ozesh, after apply your proposal, the tests included above have fail, e.g. sortBy(data, { prop: "date" }); is not working. Could you please provide me a case in plunker, jsfiddle, jsbin, etc? Thanks!

@Ozesh 2016-10-20 08:39:47

@jherax, I have edited your previous code for the reference with some new data format, you can compare it by replacing this plugin with the old one : Here is the other: link

@jherax 2016-10-21 00:16:16

@Ozesh again, thanks for your feedback. I see your point. However after testing your proposed fix in this jsfiddle is failing. I notice the bug when dealing with objects that have properties with falsy values, such as 0, false, "". The bug is fixed in this aswer, and also you can check other tests in gist: sortBy (deprecated)

@Ozesh 2016-10-21 05:34:08

@jherax Your new plugin is much better than the old one. Thanks for sharing it.

@Stobor 2009-06-11 04:12:35

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.

@bradvido 2014-05-27 13:51:53

You can use string1.localeCompare(string2) for string comparison

@Don Kirkby 2015-05-01 21:58:58

Keep in mind that localeCompare() is case insensitive. If you want case sensitive, you can use (string1 > string2) - (string1 < string2). The boolean values are coerced to integer 0 and 1 to calculate the difference.

@jlbriggs 2015-07-13 15:00:15

Is there a way to pass an argument to the compare function? Thought being to make this a reusable function to which I could pass the key on which to sort the object?

@Stobor 2015-07-23 12:52:26

@jlbriggs: see Triptych's answer below

@vjy tiwari 2017-07-25 17:42:58

What about alphanumeric strings comparison e.g. Ajay123Kumar , Kapil4Kumar562 etc ?

@Pointy 2017-08-27 12:41:18

@DonKirkby I know that's an old comment, but localeCompare() is not case insensitive in all locales; in US English in every browser I've experienced, it's consistently case-sensitive.

@Don Kirkby 2017-08-28 16:11:04

Thanks for the update, @Pointy, I don't remember running into this problem, but perhaps the behaviour has changed in the last couple of years. Regardless, the localeCompare() documentation shows that you can explicitly state whether you want case sensitivity, numeric sorting, and other options.

@Nina Scholz 2018-01-12 11:18:03

parseFloat is uperfluous, because - operator converts every operands into number.

@user1063287 2018-05-20 05:45:19

can anyone please confirm if this is correct fleshed out example of @bradvido 's answer? [{"name": "adam", id:0},{"name": "craig", id:1},{"name": "bruce", id:2}].sort(function(a, b) {return a.name.localeCompare(b.name)});

@sg28 2018-07-26 07:19:33

Good ,thanks ,but as mentioned in the MDN sort function is not reliable

@Stobor 2018-07-30 01:42:22

@sg28 I think you've misunderstood the MDN explanation. It does not say that the sort function is not reliable, it says that it is not stable. I understand why this can be confusing, but that is not a claim that it is not suitable for use. In the context of sorting algorithms, the term stable has a specific meaning - that "equal" elements in the list are sorted in the same order as in the input. This is completely unrelated to the idea of code which is unstable (i.e. not yet ready for use).

@sg28 2018-07-30 17:24:36

@Stobor , oh ok

@Valvert 2018-10-30 04:13:35

If you want to sort by a specific string values for example by city you could use: this.homes.sort((current,next)=>{ return current.city.localeCompare(next.city)});

@Nina Scholz 2019-03-27 15:56:25

why not just take the values for getting the delta: homes.sort((a, b) => a.price - b.price);

@technogeek1995 2019-05-28 15:57:47

If you're wondering if this is sorted ascending or descending order, it's sorting it in ascending order.

@Josiah Coad 2019-06-15 08:52:57

More generally ` homes.sort((a, b) => parseFloat(a[attr]) - parseFloat(b[attr])); `

@OzzyCzech 2018-03-07 07:13:45

You will need two function

function desc(a, b) {
 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}

function asc(a, b) {
  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

Then you can apply this to any object property:

 data.sort((a, b) => desc(parseFloat(a.price), parseFloat(b.price)));

let data = [
    {label: "one", value:10},
    {label: "two", value:5},
    {label: "three", value:1},
];

// sort functions
function desc(a, b) {
 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}

function asc(a, b) {
 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

// DESC
data.sort((a, b) => desc(a.value, b.value));

document.body.insertAdjacentHTML(
 'beforeend', 
 '<strong>DESCending sorted</strong><pre>' + JSON.stringify(data) +'</pre>'
);

// ASC
data.sort((a, b) => asc(a.value, b.value));

document.body.insertAdjacentHTML(
 'beforeend', 
 '<strong>ASCending sorted</strong><pre>' + JSON.stringify(data) +'</pre>'
);

@Umesh 2018-02-07 11:08:26

For a normal array of elements values only:

function sortArrayOfElements(arrayToSort) {
    function compareElements(a, b) {
        if (a < b)
            return -1;
        if (a > b)
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareElements);
}

e.g. 1:
var array1 = [1,2,545,676,64,2,24]
output : [1, 2, 2, 24, 64, 545, 676]

var array2 = ["v","a",545,676,64,2,"24"]
output: ["a", "v", 2, "24", 64, 545, 676]

For an array of objects:

function sortArrayOfObjects(arrayToSort, key) {
    function compareObjects(a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareObjects);
}

e.g. 1: var array1= [{"name": "User4", "value": 4},{"name": "User3", "value": 3},{"name": "User2", "value": 2}]

output : [{"name": "User2", "value": 2},{"name": "User3", "value": 3},{"name": "User4", "value": 4}]

@Ajay Singh 2017-08-06 17:53:28

This could have been achieved through a simple one line valueof() sort function. Run code snippet below to see demo.

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": "5",
        "city": "New York",
        "state": "NY",
        "zip": "00010",
        "price": "962500"
    }
];

console.log("To sort descending/highest first, use operator '<'");

homes.sort(function(a,b) { return a.price.valueOf() < b.price.valueOf();});

console.log(homes);

console.log("To sort ascending/lowest first, use operator '>'");

homes.sort(function(a,b) { return a.price.valueOf() > b.price.valueOf();});

console.log(homes);

@Pradip Talaviya 2017-04-26 13:13:06

For sort on multiple array object field. Enter your field name in arrprop array like ["a","b","c"] then pass in second parameter arrsource actual source we want to sort.

function SortArrayobject(arrprop,arrsource){
arrprop.forEach(function(i){
arrsource.sort(function(a,b){
return ((a[i] < b[i]) ? -1 : ((a[i] > b[i]) ? 1 : 0));
});
});
return arrsource;
}

@mythicalcoder 2017-02-07 21:39:53

Here is a slightly modified version of elegant implementation from the book "JavaScript: The Good Parts".

NOTE: This version of by is stable. It preserves the order of the first sort while performing the next chained sort.

I have added isAscending parameter to it. Also converted it to ES6 standards and "newer" good parts as recommended by the author.

You can sort ascending as well as descending and chain sort by multiple properties.

const by = function (name, minor, isAscending=true) {
    const reverseMutliplier = isAscending ? 1 : -1;
    return function (o, p) {
        let a, b;
        let result;
        if (o && p && typeof o === "object" && typeof p === "object") {
            a = o[name];
            b = p[name];
            if (a === b) {
                return typeof minor === 'function' ? minor(o, p) : 0;
            }
            if (typeof a === typeof b) {
                result = a < b ? -1 : 1;
            } else {
                result = typeof a < typeof b ? -1 : 1;
            }
            return result * reverseMutliplier;
        } else {
            throw {
                name: "Error",
                message: "Expected an object when sorting by " + name
            };
        }
    };
};

let s = [
    {first: 'Joe',   last: 'Besser'},
    {first: 'Moe',   last: 'Howard'},
    {first: 'Joe',   last: 'DeRita'},
    {first: 'Shemp', last: 'Howard'},
    {first: 'Larry', last: 'Fine'},
    {first: 'Curly', last: 'Howard'}
];

// Sort by: first ascending, last ascending
s.sort(by("first", by("last")));    
console.log("Sort by: first ascending, last ascending: ", s);     // "[
//     {"first":"Curly","last":"Howard"},
//     {"first":"Joe","last":"Besser"},     <======
//     {"first":"Joe","last":"DeRita"},     <======
//     {"first":"Larry","last":"Fine"},
//     {"first":"Moe","last":"Howard"},
//     {"first":"Shemp","last":"Howard"}
// ]

// Sort by: first ascending, last descending
s.sort(by("first", by("last", 0, false)));  
console.log("sort by: first ascending, last descending: ", s);    // "[
//     {"first":"Curly","last":"Howard"},
//     {"first":"Joe","last":"DeRita"},     <========
//     {"first":"Joe","last":"Besser"},     <========
//     {"first":"Larry","last":"Fine"},
//     {"first":"Moe","last":"Howard"},
//     {"first":"Shemp","last":"Howard"}
// ]

@mythicalcoder 2017-02-07 21:43:02

why is my answer community wiki ?

@Vishal Kumar Sahu 2017-08-14 08:29:35

could we sort {"first":"Curly","last":"Howard", "property" : {"id" : "1"}} type of array by id?

@mythicalcoder 2017-08-15 21:29:19

yes, the function has to be slightly modified to take in a new parameter, say, nestedName. You then call by with name="property", nestedName="id"

@CracyD 2016-07-26 08:43:31

With ECMAScript 6 StoBor's answer can be done even more concise:

homes.sort((a, b) => a.price - b.price)

@Evan Carroll 2016-05-25 14:53:17

Use lodash.sortBy, (instructions using commonjs, you can also just put the script include-tag for the cdn at the top of your html)

var sortBy = require('lodash.sortby');
// or
sortBy = require('lodash').sortBy;

Descending order

var descendingOrder = sortBy( homes, 'price' ).reverse();

Ascending order

var ascendingOrder = sortBy( homes, 'price' );

@mpen 2016-10-17 01:13:49

Or const sortBy = require('lodash/sortBy'); let calendars = sortBy(calendarListResponse.items, cal => cal.summary);

@montelof 2016-12-08 21:56:34

not sure if loadash changed recently by now its named OrderBy import { orderBy } from 'lodash'; ... ... return orderBy ( rows, 'fieldName' ).reverse();

@George Vrynios 2016-04-02 21:52:28

Hi after reading this article, I made a sortComparator for my needs, with the functionality to compare more than one json attributes, and i want to share it with you.

This solution compares only strings in ascending order, but the solution can be easy extended for each attribute to support: reverse ordering, other data types, to use locale, casting etc

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": "5",
    "city": "New York",
    "state": "NY",
    "zip": "00010",
    "price": "962500"

}];

// comp = array of attributes to sort
// comp = ['attr1', 'attr2', 'attr3', ...]
function sortComparator(a, b, comp) {
    // Compare the values of the first attribute
    if (a[comp[0]] === b[comp[0]]) {
        // if EQ proceed with the next attributes
        if (comp.length > 1) {
            return sortComparator(a, b, comp.slice(1));
        } else {
            // if no more attributes then return EQ
            return 0;
        }
    } else {
        // return less or great
        return (a[comp[0]] < b[comp[0]] ? -1 : 1)
    }
}

// Sort array homes
homes.sort(function(a, b) {
    return sortComparator(a, b, ['state', 'city', 'zip']);
});

// display the array
homes.forEach(function(home) {
    console.log(home.h_id, home.city, home.state, home.zip, home.price);
});

and the result is

$ node sort
4 Bevery Hills CA 90210 319250
5 New York NY 00010 962500
3 Dallas TX 75201 162500

and another sort

homes.sort(function(a, b) {
    return sortComparator(a, b, ['city', 'zip']);
});

with result

$ node sort
4 Bevery Hills CA 90210 319250
3 Dallas TX 75201 162500
5 New York NY 00010 962500

@Eneko Alonso 2015-09-25 02:37:47

While it is a bit of an overkill for just sorting a single array, this prototype function allows to sort Javascript arrays by any key, in ascending or descending order, including nested keys, using dot syntax.

(function(){
    var keyPaths = [];

    var saveKeyPath = function(path) {
        keyPaths.push({
            sign: (path[0] === '+' || path[0] === '-')? parseInt(path.shift()+1) : 1,
            path: path
        });
    };

    var valueOf = function(object, path) {
        var ptr = object;
        for (var i=0,l=path.length; i<l; i++) ptr = ptr[path[i]];
        return ptr;
    };

    var comparer = function(a, b) {
        for (var i = 0, l = keyPaths.length; i < l; i++) {
            aVal = valueOf(a, keyPaths[i].path);
            bVal = valueOf(b, keyPaths[i].path);
            if (aVal > bVal) return keyPaths[i].sign;
            if (aVal < bVal) return -keyPaths[i].sign;
        }
        return 0;
    };

    Array.prototype.sortBy = function() {
        keyPaths = [];
        for (var i=0,l=arguments.length; i<l; i++) {
            switch (typeof(arguments[i])) {
                case "object": saveKeyPath(arguments[i]); break;
                case "string": saveKeyPath(arguments[i].match(/[+-]|[^.]+/g)); break;
            }
        }
        return this.sort(comparer);
    };    
})();

Usage:

var data = [
    { name: { first: 'Josh', last: 'Jones' }, age: 30 },
    { name: { first: 'Carlos', last: 'Jacques' }, age: 19 },
    { name: { first: 'Carlos', last: 'Dante' }, age: 23 },
    { name: { first: 'Tim', last: 'Marley' }, age: 9 },
    { name: { first: 'Courtney', last: 'Smith' }, age: 27 },
    { name: { first: 'Bob', last: 'Smith' }, age: 30 }
]

data.sortBy('age'); // "Tim Marley(9)", "Carlos Jacques(19)", "Carlos Dante(23)", "Courtney Smith(27)", "Josh Jones(30)", "Bob Smith(30)"

Sorting by nested properties with dot-syntax or array-syntax:

data.sortBy('name.first'); // "Bob Smith(30)", "Carlos Dante(23)", "Carlos Jacques(19)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"
data.sortBy(['name', 'first']); // "Bob Smith(30)", "Carlos Dante(23)", "Carlos Jacques(19)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"

Sorting by multiple keys:

data.sortBy('name.first', 'age'); // "Bob Smith(30)", "Carlos Jacques(19)", "Carlos Dante(23)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"
data.sortBy('name.first', '-age'); // "Bob Smith(30)", "Carlos Dante(23)", "Carlos Jacques(19)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"

You can fork the repo: https://github.com/eneko/Array.sortBy

@Tim Gilbert 2009-06-11 04:14:48

You want to sort it in Javascript, right? What you want is the sort() function. In this case you need to write a comparator function and pass it to sort(), so something like this:

function comparator(a, b) {
    return parseInt(a["price"], 10) - parseInt(b["price"], 10);
}

var json = { "homes": [ /* your previous data */ ] };
console.log(json["homes"].sort(comparator));

Your comparator takes one of each of the nested hashes inside the array and decides which one is higher by checking the "price" field.

@Bergi 2014-09-01 16:03:42

@BeetleJuice 2016-06-21 04:49:28

parseInt may be a bad idea to use with price. Will it accurately sort non-integers? (15.10 or 15.15). I'd use parseFloat instead.

@Ricardo Marimon 2009-06-11 04:11:08

To sort it you need to create a comparator function taking two arguments. Then call the sort function with that comparator function as follows:

// a and b are object elements of your array
function mycomparator(a,b) {
  return parseInt(a.price, 10) - parseInt(b.price, 10);
}
homes.sort(mycomparator);

If you want to sort ascending switch the expressions on each side of the minus sign.

@Kevin Hakanson 2009-06-11 04:17:17

Here's a reference to the built in Array sort method - w3schools.com/jsref/jsref_sort.asp

@dmonopoly 2013-03-08 16:36:42

For me, sorting ascending went the way that was originally coded: a.price - b.price

@Roland Illig 2014-05-25 20:30:34

And here's a reference that actually explains the topic instead of saying "it's too complicated, you won't understand it anyway": developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

@BeetleJuice 2016-06-21 04:48:44

parseInt may be a bad idea to use with price. Will it accurately sort non-integers? (15.10 or 15.15). I'd use parseFloat instead.

@Vitalii Fedorenko 2015-05-06 01:41:02

If you use Underscore.js, try sortBy:

// price is of an integer type
_.sortBy(homes, "price"); 

// price is of a string type
_.sortBy(homes, function(home) {return parseInt(home.price);}); 

@Triptych 2009-06-11 04:33:59

Here's a more flexible version, which allows you to create reusable sort functions, and sort by any field.

var sort_by = function(field, reverse, primer){

   var 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...

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": "5",
   "city": "New York",
   "state": "NY",
   "zip": "00010",
   "price": "962500"

}];

// Sort by price high to low
homes.sort(sort_by('price', true, parseInt));

// Sort by city, case-insensitive, A-Z
homes.sort(sort_by('city', false, function(a){return a.toUpperCase()}));

@amelvin 2010-11-23 10:02:21

+1 Good extensible solution, especially impressed with the ability to do a one line sort on every field in the OPs question.

@diEcho 2010-12-24 10:04:10

if we want to sort by date then??

@diEcho 2010-12-24 10:19:41

i tried by home.sort(sort_by('start_time', true, function(a){return a.getTime()})); but display error a.getTime is not a function

@nickb 2011-10-31 05:47:08

Even though this is super cool, isn't it terribly inefficient. The speed would be O(n*n). Any way to use a more efficient sort algorithm, like Quick Sort while also keeping it extensible like your answer above?

@Triptych 2011-10-31 07:04:09

nickb - you're misreading the code. sort_by runs in O(1), and returns a function used by the built-in sort (O(N log N)) to compare items in a list. The total complexity is O(n log n) * O(1) which reduces to O(n log n), or the same as a quick sort.

@Justin Lucente 2011-12-02 22:57:32

Excellent stuff here. I'm also wondering how to get this to sort by date (re: diEcho). Not sure how to work in something such as: new Date(homes.start_time) in order to use a getTime(), then sort. Any ideas?

@Triptych 2011-12-02 23:16:37

@Justin passing something like function(obj){return new Date(obj.start_time)} as the primer argument ought to get it done...

@Halil Özgür 2011-12-09 15:52:59

Excellent idea! A few issues: 1-A left parenthesis seems to be in the wrong place. 2-Setting the reverse looks reverse :) 3-Line break seems to cause issues. Overall, shouldn't that one-liner be return (A < B ? -1 : (A > B ? 1 : 0)) * [1,-1][+!!reverse]; ?

@Triptych 2012-01-25 01:29:57

@Halil I'd love to make to a one-liner and probably would in real code, but I'm keeping the operators lined up for newbie readers...

@Abby 2012-04-26 13:42:40

One issue I have with this is that with reverse=false, it will sort numbers as 1,2,3,4... but Strings as z,y,x...

@ErikE 2012-08-07 01:18:00

A small enhancement: var key = primer ? function (x) { return primer(x[field]); } : function (x) { return x[field]; }

@user418775 2012-08-26 12:52:33

I tried this answer, but got this error: Type error 'undefined' is not an object (evaluating 'a.toUpperCase')

@Blake Mills 2013-01-17 04:32:07

Here is a working jsfiddle vesrion of this code: jsfiddle.net/dFNva/1

@Jake Coxon 2013-05-03 17:24:03

Just for fun: return ((A > B) - (B > A)) * [-1,1][+!!reverse];

@EleventyOne 2013-08-29 20:06:29

Note that the !!reverse makes the results descending by default (as the jsfiddle code above highlights as well. If you want ascending by default, just make it !reverse.

@Ingo Bürk 2013-12-03 21:28:52

While [1,-1][+!!reverse] looks cool, it's a horrible thing to do. If a user can't call your method properly, punish him, not try to somehow make sense of it, no matter what.

@AlanJames 2014-02-09 00:46:46

Excellent, works like a charm. I was just wondering if anyone could would know how to take this one step further. Say I had the same array given in the example above and wanted to sort by price, but with a lot more objects, say 100. Now if I had some objects that I wanted "highlighted", so I added an extra field to all objects called "Highlighted" which is either 1 or 0. I want the highlighted objects to always be on top of the list but they should also be sorted be price (ie highlighted objects sorted by price...followed by non-highlighted objects sorted by price). Any ideas on how to do it ?

@Jason 2014-03-19 19:27:04

This is awesome, but what if I want to sort by a nested property, a la {startDate: {year: 2014, month: 3}} ?

@gfullam 2014-05-23 15:24:29

I just found the explanation: + converts boolean to number; !! converts non-boolean to boolean. (dreaminginjavascript.wordpress.com/2008/07/04/28) So, [+!!reverse] provides an index for the [-1,1] array evaluating to either [-1,1][0] or [-1,1][1], which evaluates to -1 or 1. That's awesome, but confusing.

@gfullam 2014-05-23 18:09:28

Here is a fiddle based on @Blake Mills' fiddle: jsfiddle.net/gfullam/sq9U7 | It fixes the bug noted by Abby and implements "then by" sorting requested by AlanJames using the Crockford method of passing in another sort by function call as an option.

@Gerrit Brink 2015-03-05 14:14:08

Wouldn't it be better to prepare the source data, this would cause consecutive parsing when clearly the source data needs some tweaking.

@MatFiz 2016-08-26 08:27:08

I found it quite usefull to add to to Object prototype, so you can easily use it at any object: javascript Object.prototype.sort_by = function(field,reverse,primer) { var sort_by = function(field, reverse, primer){ var 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)); } } return this.sort(sort_by(field,reverse,primer)) }

@jpmc26 2017-01-13 17:28:49

Thanks. Sorting by key is vastly superior to having to develop your own comparitors in most cases.

@Mehrdad Babaki 2018-12-03 22:46:33

@Triptych I was wondering if we can compare strings, for example, city directly instead of writing sort_by function?

@user3346960 2015-01-31 01:55:10

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

@Brad Bird 2014-10-30 10:28:23

I recently wrote a universal function to manage this for you if you want to use it.

/**
 * Sorts an object into an order
 *
 * @require jQuery
 *
 * @param object Our JSON object to sort
 * @param type Only alphabetical at the moment
 * @param identifier The array or object key to sort by
 * @param order Ascending or Descending
 *
 * @returns Array
 */
function sortItems(object, type, identifier, order){

    var returnedArray = [];
    var emptiesArray = []; // An array for all of our empty cans

    // Convert the given object to an array
    $.each(object, function(key, object){

        // Store all of our empty cans in their own array
        // Store all other objects in our returned array
        object[identifier] == null ? emptiesArray.push(object) : returnedArray.push(object);

    });

    // Sort the array based on the type given
    switch(type){

        case 'alphabetical':

            returnedArray.sort(function(a, b){

                return(a[identifier] == b[identifier]) ? 0 : (

                    // Sort ascending or descending based on order given
                    order == 'asc' ? a[identifier] > b[identifier] : a[identifier] < b[identifier]

                ) ? 1 : -1;

            });

            break;

        default:

    }

    // Return our sorted array along with the empties at the bottom depending on sort order
    return order == 'asc' ? returnedArray.concat(emptiesArray) : emptiesArray.concat(returnedArray);

}

@Rodolfo Jorge Nemer Nogueira 2014-09-02 13:44:37

I also worked with some kind of rating and multiple fields sort:

arr = [
    {type:'C', note:834},
    {type:'D', note:732},
    {type:'D', note:008},
    {type:'F', note:474},
    {type:'P', note:283},
    {type:'P', note:165},
    {type:'X', note:173},
    {type:'Z', note:239},
];

arr.sort(function(a,b){        
    var _a = ((a.type==='C')?'0':(a.type==='P')?'1':'2');
    _a += (a.type.localeCompare(b.type)===-1)?'0':'1';
    _a += (a.note>b.note)?'1':'0';
    var _b = ((b.type==='C')?'0':(b.type==='P')?'1':'2');
    _b += (b.type.localeCompare(a.type)===-1)?'0':'1';
    _b += (b.note>a.note)?'1':'0';
    return parseInt(_a) - parseInt(_b);
});

Result

[
    {"type":"C","note":834},
    {"type":"P","note":165},
    {"type":"P","note":283},
    {"type":"D","note":8},
    {"type":"D","note":732},
    {"type":"F","note":474},
    {"type":"X","note":173},
    {"type":"Z","note":239}
]

@bob 2014-01-28 07:15:05

Here is a culmination of all answers above.

Fiddle validation: http://jsfiddle.net/bobberino/4qqk3/

var sortOn = function (arr, prop, reverse, numeric) {

    // Ensure there's a property
    if (!prop || !arr) {
        return arr
    }

    // Set up sort function
    var sort_by = function (field, rev, primer) {

        // Return the required a,b function
        return function (a, b) {

            // Reset a, b to the field
            a = primer(a[field]), b = primer(b[field]);

            // Do actual sorting, reverse as needed
            return ((a < b) ? -1 : ((a > b) ? 1 : 0)) * (rev ? -1 : 1);
        }

    }

    // Distinguish between numeric and string to prevent 100's from coming before smaller
    // e.g.
    // 1
    // 20
    // 3
    // 4000
    // 50

    if (numeric) {

        // Do sort "in place" with sort_by function
        arr.sort(sort_by(prop, reverse, function (a) {

            // - Force value to a string.
            // - Replace any non numeric characters.
            // - Parse as float to allow 0.02 values.
            return parseFloat(String(a).replace(/[^0-9.-]+/g, ''));

        }));
    } else {

        // Do sort "in place" with sort_by function
        arr.sort(sort_by(prop, reverse, function (a) {

            // - Force value to string.
            return String(a).toUpperCase();

        }));
    }


}

@TechTurtle 2017-09-28 16:59:11

can you please explain what is the significance of having * (rev ? -1 : 1);

@bob 2017-09-29 18:16:52

That's to reverse the order (ascending vs descending) the rev portion just flips normal results when the rev argument is true. Otherwise it'll just multiple by 1 which does nothing, when set, it'll multiply the result by -1, thereby inverting the result.

@Lalit Kumar 2013-12-06 10:10:44

For sorting a array you must define a comparator function. This function always be different on your desired sorting pattern or order(i.e. ascending or descending).

Let create some functions that sort an array ascending or descending and that contains object or string or numeric values.

function sorterAscending(a,b) {
    return a-b;
}

function sorterDescending(a,b) {
    return b-a;
}

function sorterPriceAsc(a,b) {
    return parseInt(a['price']) - parseInt(b['price']);
}

function sorterPriceDes(a,b) {
    return parseInt(b['price']) - parseInt(b['price']);
}

Sort numbers (alphabetically and ascending):

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();

Sort numbers (alphabetically and descending):

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
fruits.reverse();

Sort numbers (numerically and ascending):

var points = [40,100,1,5,25,10];
points.sort(sorterAscending());

Sort numbers (numerically and descending):

var points = [40,100,1,5,25,10];
points.sort(sorterDescending());

As above use sorterPriceAsc and sorterPriceDes method with your array with desired key.

homes.sort(sorterPriceAsc()) or homes.sort(sorterPriceDes())

@Ishan Liyanage 2013-11-14 05:55:48

for string sorting in case some one needs it,

var dataArr = {  

    "hello": [{
    "id": 114,
    "keyword": "zzzzzz",
    "region": "Sri Lanka",
    "supportGroup": "administrators",
    "category": "Category2"
}, {
    "id": 115,
    "keyword": "aaaaa",
    "region": "Japan",
    "supportGroup": "developers",
    "category": "Category2"
}]

};
var sortArray = dataArr['hello'];
sortArray.sort(function(a,b) {
    if ( a.region < b.region )
        return -1;
    if ( a.region > b.region )
        return 1;
    return 0;
} );

@John G 2009-06-11 04:14:53

You can use the JavaScript sort method with a callback function:

function compareASC(homeA, homeB)
{
    return parseFloat(homeA.price) - parseFloat(homeB.price);
}

function compareDESC(homeA, homeB)
{
    return parseFloat(homeB.price) - parseFloat(homeA.price);
}

// Sort ASC
homes.sort(compareASC);

// Sort DESC
homes.sort(compareDESC);

Related Questions

Sponsored Content

27 Answered Questions

[SOLVED] What does "use strict" do in JavaScript, and what is the reasoning behind it?

39 Answered Questions

[SOLVED] Loop through an array in JavaScript

69 Answered Questions

[SOLVED] What is the most efficient way to deep clone an object in JavaScript?

3 Answered Questions

79 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 5834426 View
  • 7275 Score
  • 79 Answer
  • Tags:   javascript arrays

46 Answered Questions

38 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

86 Answered Questions

[SOLVED] How do JavaScript closures work?

41 Answered Questions

[SOLVED] Sort array of objects by string property value

33 Answered Questions

[SOLVED] For-each over an array in JavaScript?

Sponsored Content