Sort JavaScript object by key
Asked Answered
B

38

846

I need to sort JavaScript objects by key.

Hence the following:

{ 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }

Would become:

{ 'a' : 'dsfdsfsdf', 'b' : 'asdsad', 'c' : 'masdas' }
Burin answered 29/3, 2011 at 2:8 Comment(10)
possible duplicate of Sorting a JSON object in JavascriptCharnel
Back in 2011 (when this question was posted), the ECMAScript spec said that JavaScript objects don’t have an inherent order — the observed order was implementation-dependent and thus couldn’t be relied upon. However, it turns out all JavaScript engines implemented more or less the same semantics, so those have now been standardized in ES6. As a result, a lot of the answers below used to be correct as per the spec, but are now incorrect.Bialy
shortly saying use sorted stringify when you need to compare or hash the results: npmjs.com/package/json-stable-stringifyPunjab
Given that objects are just maps, or dicts depending on your language, there is little to no reason why you would do this. THAT BEING SAID, Generally, the order that they are injected into a map is in fact the order they reside when stringifying. SO, if you created a new map and assigned values based on a presorted key list, you will find yourself an ordered map based on keysSama
Note that ever since Object.entries and Object.fromEntries were added to JS, this can be achieved with a nicely short one-liner: Object.fromEntries(Object.entries(obj).sort())Welt
Worth of look: sitepoint.com/sort-an-array-of-objects-in-javascriptJankell
If you’re looking for sorting an array of objects by properties, see Sorting objects by property values.Consolidation
to recursively sort a javascript object by key - https://mcmap.net/q/37304/-sorting-javascript-object-by-key-value-recursively - i.e. to sort an object and also objects contained withinResponsiveness
Probably just use ECMAScript spec to inherent order - #51539659Geotropism
This is an common XY problem. Even if you can now rely on order doesn't mean you should, in almost all cases. Objects aren't designed for iteration, they're designed for named property access. Consider using an array if you want order and iteration, rather than packing and unpacking objects with Object.entries() and Object.fromEntries(). These should be used sparingly and in contexts where order is unimportant.Glaudia
B
828

The other answers to this question are outdated, never matched implementation reality, and have officially become incorrect now that the ES6 / ES2015 spec has been published.


See the section on property iteration order in Exploring ES6 by Axel Rauschmayer:

All methods that iterate over property keys do so in the same order:

  1. First all Array indices, sorted numerically.
  2. Then all string keys (that are not indices), in the order in which they were created.
  3. Then all symbols, in the order in which they were created.

So yes, JavaScript objects are in fact ordered, and the order of their keys/properties can be changed.

Here’s how you can sort an object by its keys/properties, alphabetically:

const unordered = {
  'b': 'foo',
  'c': 'bar',
  'a': 'baz'
};

console.log(JSON.stringify(unordered));
// → '{"b":"foo","c":"bar","a":"baz"}'

const ordered = Object.keys(unordered).sort().reduce(
  (obj, key) => { 
    obj[key] = unordered[key]; 
    return obj;
  }, 
  {}
);

console.log(JSON.stringify(ordered));
// → '{"a":"baz","b":"foo","c":"bar"}'

Use var instead of const for compatibility with ES5 engines.

Bialy answered 28/6, 2015 at 17:23 Comment(18)
I really cant see a difference to your code and the top answer here apart from using a slightly different looping technique. Whether or not the objects can be said to be "ordered" or not seems to be irrelevant. The answer to this question is still the same. The published spec merely confirms the answers here.Hundredpercenter
FYI, it was clarified that the enumeration order of properties is still undefined: esdiscuss.org/topic/…Barrage
@Phil_1984_ This answer and top voted answer are very different. OP's question was how to sort an object literal. Top voted answer says you can't, then gives a workaround by storing sorted keys in an array, then iterating and printing key value pairs from the sorted array. This answer claims that the order of object literals are now sortable and his example stores the sorted key values back to an object literal, then prints the sorted object directly. On a side note, it would be nice if the linked site still existed.Apps
Both answers simply use the Array.sort function to sort the keys first. The OP is asking to sort a "JavaScript object" and is merely using JavaScript Object Notation (JSON) to describe the 2 objects. These 2 objects are logically identical meaning sorting is irrelevant. I think the top answer explains this a lot better. Saying "all other answers are now officially incorrect" is too extreme for me, especially with a broken link. I think the problem is "this new ES6 spec" is giving the illusion that Javascript objects have an ordered list of keys which is simply not true.Hundredpercenter
Please add that this solution is not supported by a variety of modern browsers (google "caniuse ES6"). Using this answers risks hard-to-find bugs in certain browsers only (e.g. Safari when Chrome is all fine).Oxtail
@ManuelArwedSchmidt Browser support for ES6 is not binary — ES6 is not just a single feature. Can you name one modern browser in which the above does not work?Bialy
@FagnerBrack The new link is exploringjs.com/es6/… but the contents have changed.Bialy
@MathiasBynens That's unfortunate =/. Maybe edit the answer removing the link and stating that the contents of the original link has changed?Retroaction
i am working with SOAP server and using Nodejs strong-soap as a SOAP client. The object gets parsed into a SOAP message and the SOAP server wants it in alphabetical order. A solution like this is necessary in order for submission. Thanks a lot!Schuck
link is broken?Burton
Surprisingly, the chrome.storage API still sorts object keys in lexicographic order, which is not even consistent with Chrome V8.Clergy
What to do If I need them in reverse order? Below code is not working: Object.keys(RES).sort(function(a,b){return b-a;}).forEach(function(key) {RES1[key] = RES[key];}); Neither: Object.keys(P).sort().reverse().forEach(function(key) {P1[key] = P[key];}); is working.Glyph
The link says that "Own Property Keys" are ordered but that "Enumerable Own Names" are not and the latter controls for JSON: "The order is not defined by ES6, but it must be the same order in which for-in traverses properties. Used by: JSON.parse(), JSON.stringify(), Object.keys()" So the documentation referenced explicitly says that JSON uses a undefined ordering! Yet the example provided works everywhere I tired... but I'd still like to know if that's by happenstance or because it's specified that way.Overstuff
@MathiasBynens The ES2020 semantics of JavaScript objects are that they are not ordered. #30076719Thirsty
Worth noting that, whenever order is required, it might be better to use an array. Ordering by creation time isn't needed most of the time, and reinserting all key/values whenever some entry gets added/removed is certainly bad design. If you catch yourself doing that, don't. Use an array!Bickering
Note that rather than Object.keys, modern JS (as of the time of this comment) offers Object.entries and Object.fromEntries, which means this it's probably worth editing this answer to include the approach in https://mcmap.net/q/37199/-sort-javascript-object-by-keyWelt
I guess we can use Array.reduce like: obj => Object.keys(obj).sort().reduce((acc, current) => { acc[current] = obj[current]; return acc; }, {});Minter
You can also add a.toLowerCase().localeCompare(b.toLowerCase()) to the sort function to ignore capital sortBaluchistan
W
263

JavaScript objects1 are not ordered. It is meaningless to try to "sort" them. If you want to iterate over an object's properties, you can sort the keys and then retrieve the associated values:

var myObj = {
    'b': 'asdsadfd',
    'c': 'masdasaf',
    'a': 'dsfdsfsdf'
  },
  keys = [],
  k, i, len;

for (k in myObj) {
  if (myObj.hasOwnProperty(k)) {
    keys.push(k);
  }
}

keys.sort();

len = keys.length;

for (i = 0; i < len; i++) {
  k = keys[i];
  console.log(k + ':' + myObj[k]);
}

Alternate implementation using Object.keys fanciness:

var myObj = {
    'b': 'asdsadfd',
    'c': 'masdasaf',
    'a': 'dsfdsfsdf'
  },
  keys = Object.keys(myObj),
  i, len = keys.length;

keys.sort();

for (i = 0; i < len; i++) {
  k = keys[i];
  console.log(k + ':' + myObj[k]);
}

1Not to be pedantic, but there's no such thing as a JSON object.

Wacky answered 29/3, 2011 at 2:11 Comment(15)
Excellent answer here's my own implementation in a real world situation: gist.github.com/clouddueling/5242726Meetly
@MarcelKorpel There is such thing as a JSON object. Check section 8 of the official JSON RFC: ietf.org/rfc/rfc4627.txtPernell
@Paulpro two things to note about that RFC: first, it's 7 years old at this point, and vocabulary changes over time; second, "This memo provides information for the Internet community. It does not specify an Internet standard of any kind." Whether a given sequence of characters represents a JavaScript object literal or a JSON text depends on context/usage. The term "JSON object" conflates and makes the distinction ambiguous in a detrimental way. Let's be rid of the imprecise terminology, and use the more precise term where possible. I see no reason to do otherwise. Words matter.Wacky
@Paulpro as linked in my answer: benalman.com/news/2010/03/theres-no-such-thing-as-a-jsonWacky
@MattBall IMO JSON Object is a very precise term for a string like {"a", 1} just as JSON Array is precise term for a string like [1]. It is useful to be able to communicate by saying things like the third object in my array when you have the string [{x: 1}, {y: 2}, {z: 3}], so I much prefer "That is not a JSON object" when commenting about a Javascript literal, rather then "There is no such thing as a JSON object", which is just going to cause more confusion and communication difficulties later when the OP actually is working with JSON.Pernell
@Paulpro I must disagree. {"a", 1} is either an object literal or a JSON text (aka JSON string, if you really prefer). Which it is depends on context, the former if it appears verbatim within JavaScript source code, the latter if it's a string that needs to be passed to a JSON parser to be used further. There are real differences between the two when it comes to allowed syntax, correct usage, and serialization.Wacky
@MattBall I am referring to it in a string context of course, and yes it is a JSON text, but [{x: 1}, {y: 2}, {z: 3}] is also a JSON text which consists of 3 JSON objects in a JSON array.Pernell
@Paulpro but that's not valid JSON! It's a valid JavaScript literal, however. If it were valid JSON, I describe it as a JSON text comprised of an array whose elements are 3 objects. The thing you describe, in my mind, would be something like this: '["{\"x\": 1}", "{\"y\": 2}", "{\"z\": 3}"]'. Re-identifying the inner objects as JSON implies that they should be parsed by a JSON parser. Remember that JSON is a text format. You say "a string context of course" but that's not obvious when you write something like [{"x": 1}, {"y": 2}, {"z": 3}]. It could be JSON,Wacky
or it could be an array literal, but it depends on context. We use terminology to disambiguate. Do you disagree that the terminology I'm advocating is less ambiguous than "JSON object?"Wacky
@MattBall I guess I see JSON Object as an unambiguous term (that is usually used incorrectly) for a substring of JSON that begins with a { character and ends with a } character. I wish that people would say JSON Object when that is exactly what they mean, not when they are referring to a Javascript object literal, nor a JSON text that begins with [.Pernell
@Paulpro right. The problem is that people do misuse it when they really mean a (JavaScript) object literal.Wacky
Now that ES6/ES2015 is finalized, this answer has officially become incorrect. See my answer for more info.Bialy
@Iscariot what do you mean by "does not work?" Keys are always strings, never numbers.Wacky
One reason that sorting JSON data is helpful: Comparing 2 data files for differences. Yes you can do so programmatically, but JSON is a text format which sometimes needs to compared quickly and visually.Nomadize
To sort nested json object by key recursivelyDespair
B
251

A lot of people have mention that "objects cannot be sorted", but after that they are giving you a solution which works. Paradox, isn't it?

No one mention why those solutions are working. They are, because in most of the browser's implementations values in objects are stored in the order in which they were added. That's why if you create new object from sorted list of keys it's returning an expected result.

And I think that we could add one more solution – ES5 functional way:

function sortObject(obj) {
    return Object.keys(obj).sort().reduce(function (result, key) {
        result[key] = obj[key];
        return result;
    }, {});
}

ES2015 version of above (formatted to "one-liner"):

const sortObject = o => Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})

Short explanation of above examples (as asked in comments):

Object.keys is giving us a list of keys in provided object (obj or o), then we're sorting those using default sorting algorithm, next .reduce is used to convert that array back into an object, but this time with all of the keys sorted.

Bagasse answered 14/4, 2015 at 8:33 Comment(5)
@Pointy This behavior has always available in all major browsers, and has been standardized in ES6/ES2015. I’d say this is good advice.Bialy
This is the simplest and most concise way of accomplishing task in EcmaScript v5. A bit late to the party but should be the accepted answer.Evacuate
"They are, because in most of the browser's implementations values in objects are stored in the order in which they were added" Only for non-numerical properties though. Also note that there is still no guarantee in which order the properties are iterated over (e.g. via for...in).Barrage
True one liner: const sortObject = o => Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})Apps
My linter complained about that one-liner (returning an assignment), but this one works for me and is easier for me to read: Object.keys(dict).sort().reduce((r, k) => Object.assign(r, { [k]: dict[k] }), {});Nonconformity
I
101

Guys I'm figuratively shocked! Sure all answers are somewhat old, but no one did even mention the stability in sorting! So bear with me I'll try my best to answer the question itself and go into details here. So I'm going to apologize now it will be a lot to read.

Since it is 2018 I will only use ES6, the Polyfills are all available at the MDN docs, which I will link at the given part.


Answer to the question:

If your keys are only numbers then you can safely use Object.keys() together with Array.prototype.reduce() to return the sorted object:

// Only numbers to show it will be sorted.
const testObj = {
  '2000': 'Articel1',
  '4000': 'Articel2',
  '1000': 'Articel3',
  '3000': 'Articel4',
};

// I'll explain what reduces does after the answer.
console.log(Object.keys(testObj).reduce((accumulator, currentValue) => {
  accumulator[currentValue] = testObj[currentValue];
  return accumulator;
}, {}));

/**
 * expected output:
 * {
 * '1000': 'Articel3',
 * '2000': 'Articel1',
 * '3000': 'Articel4',
 * '4000': 'Articel2' 
 *  } 
 */

// if needed here is the one liner:
console.log(Object.keys(testObj).reduce((a, c) => (a[c] = testObj[c], a), {}));

However if you are working with strings I highly recommend chaining Array.prototype.sort() into all of this:

// String example
const testObj = {
  'a1d78eg8fdg387fg38': 'Articel1',
  'z12989dh89h31d9h39': 'Articel2',
  'f1203391dhj32189h2': 'Articel3',
  'b10939hd83f9032003': 'Articel4',
};
// Chained sort into all of this.
console.log(Object.keys(testObj).sort().reduce((accumulator, currentValue) => {
  accumulator[currentValue] = testObj[currentValue];
  return accumulator;
}, {}));

/**
 * expected output:   
 * { 
 * a1d78eg8fdg387fg38: 'Articel1',
 * b10939hd83f9032003: 'Articel4',
 * f1203391dhj32189h2: 'Articel3',
 * z12989dh89h31d9h39: 'Articel2' 
 * }
 */

// again the one liner:
console.log(Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}));

If someone is wondering what reduce does:

// Will return Keys of object as an array (sorted if only numbers or single strings like a,b,c).
Object.keys(testObj)

// Chaining reduce to the returned array from Object.keys().
// Array.prototype.reduce() takes one callback 
// (and another param look at the last line) and passes 4 arguments to it: 
// accumulator, currentValue, currentIndex and array
.reduce((accumulator, currentValue) => {

  // setting the accumulator (sorted new object) with the actual property from old (unsorted) object.
  accumulator[currentValue] = testObj[currentValue];

  // returning the newly sorted object for the next element in array.
  return accumulator;

  // the empty object {} ist the initial value for  Array.prototype.reduce().
}, {});

If needed here is the explanation for the one liner:

Object.keys(testObj).reduce(

  // Arrow function as callback parameter.
  (a, c) => 

  // parenthesis return! so we can safe the return and write only (..., a);
  (a[c] = testObj[c], a)

  // initial value for reduce.
  ,{}
);

Why Sorting is a bit complicated:

In short Object.keys() will return an array with the same order as we get with a normal loop:

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.keys(object1));
// expected output: Array ["a", "b", "c"]

Object.keys() returns an array whose elements are strings corresponding to the enumerable properties found directly upon object. The ordering of the properties is the same as that given by looping over the properties of the object manually.

Sidenote - you can use Object.keys() on arrays as well, keep in mind the index will be returned:

// simple array
const arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

But it is not as easy as shown by those examples, real world objects may contain numbers and alphabetical characters or even symbols (please don't do it).

Here is an example with all of them in one object:

// This is just to show what happens, please don't use symbols in keys.
const testObj = {
  '1asc': '4444',
  1000: 'a',
  b: '1231',
  '#01010101010': 'asd',
  2: 'c'
};

console.log(Object.keys(testObj));
// output: [ '2', '1000', '1asc', 'b', '#01010101010' ]

Now if we use Array.prototype.sort() on the array above the output changes:

console.log(Object.keys(testObj).sort());
// output: [ '#01010101010', '1000', '1asc', '2', 'b' ]

Here is a quote from the docs:

The sort() method sorts the elements of an array in place and returns the array. The sort is not necessarily stable. The default sort order is according to string Unicode code points.

The time and space complexity of the sort cannot be guaranteed as it is implementation dependent.

You have to make sure that one of them returns the desired output for you. In reallife examples people tend to mix up things expecially if you use different information inputs like APIs and Databases together.


So what's the big deal?

Well there are two articles which every programmer should understand:

In-place algorithm:

In computer science, an in-place algorithm is an algorithm which transforms input using no auxiliary data structure. However a small amount of extra storage space is allowed for auxiliary variables. The input is usually overwritten by the output as the algorithm executes. In-place algorithm updates input sequence only through replacement or swapping of elements. An algorithm which is not in-place is sometimes called not-in-place or out-of-place.

So basically our old array will be overwritten! This is important if you want to keep the old array for other reasons. So keep this in mind.

Sorting algorithm

Stable sort algorithms sort identical elements in the same order that they appear in the input. When sorting some kinds of data, only part of the data is examined when determining the sort order. For example, in the card sorting example to the right, the cards are being sorted by their rank, and their suit is being ignored. This allows the possibility of multiple different correctly sorted versions of the original list. Stable sorting algorithms choose one of these, according to the following rule: if two items compare as equal, like the two 5 cards, then their relative order will be preserved, so that if one came before the other in the input, it will also come before the other in the output.

enter image description here

An example of stable sort on playing cards. When the cards are sorted by rank with a stable sort, the two 5s must remain in the same order in the sorted output that they were originally in. When they are sorted with a non-stable sort, the 5s may end up in the opposite order in the sorted output.

This shows that the sorting is right but it changed. So in the real world even if the sorting is correct we have to make sure that we get what we expect! This is super important keep this in mind as well. For more JavaScript examples look into the Array.prototype.sort() - docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Illustration answered 7/8, 2018 at 11:13 Comment(14)
You flippin rock, thank you for this incredible answer. One of the best I've seen on SO. Cheers.Lw
If only you could provide a freaking method to use at the end. Great answer though!Bauer
@momomo the problem is, depending on what you expect from sorting, there is no right method. However you can simply use this piece of code from my answer: Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}).Illustration
Isn't stability of the sort not applicable to this question: we are sorting by object key, and the key is unique. (To extend your card example: there can never be two 5s in the pack, even if they are of different suits.)Graecize
@DarrenCook good question! You are right there will never be the same key in one object. However the stability is more complex than just the uniqueness of a key. Most of the time an array is included in sorting objects. And that is when everything can become unstable. Imagine a card game with 5 players. Each hand is represented by an array (to keep an individual hand sorting) and the cards as objects. If your card looks like this {5: 'hearts'} or {5: 'spades'} and you start sorting the array it will become potentially unstable in games like rummy. Not to speak of different languages.Illustration
Yes, but I think the problem with (the second half of) this answer is that is a high-quality answer to another question. :-) So in the context of this question it is diluting the useful information you do have, and makes the answer overall a bit confusing.Graecize
@DarrenCook Yes, the second half could be better placed in an other question. But I am pretty sure that most of the people searching for this question have no intention to learn such "deeper" knowledge and will just read the first codeblock. However I'm trying to ignite a spark in those who are curious and interested. You could say I did put the side-effect information on purpose in there because it is a commonly asked question. Which then again could confuse some people...Illustration
The Array.prototype.sort() documentation says it actually is stable for all modern browsers. Does it mean that result of sorting cards from example will always be same?Natty
@ArthurStankevich it all depends on your expectation. Yes the Array.prototype.sort() is stable. However if you have multiple sorting criteria, the problem will arise. Think about the card game, will you sort for the numbers or the symbol? Is there a way to do it for both? If you do a simple sort like: ['7hearts', '5hearts', '2hearts', '5diamonds'].sort(), the results will stay the same. If you put in your own rules (compareFunction ), you have to watch out for stability.Illustration
@Illustration this is interesting, thank you. Are you saying that sort() is unstable in case of custom compareFunction even if it is deterministic?Natty
@ArthurStankevich, it depends highly on the versions, complexity and the used types. However I can say that with the newer version of the used JavaScript Engine the outputs are stable so far. So if you have tests to determine outcomes, you can be sure that the supported version, will have the same results. The version are found at the very bottom of the MDN Documentation for: Array.prototype.sort(). Keep in mind that in the real world there are version mismatches, where you will most likely have errors even in deterministic sorts, because they behave differently in older versions.Illustration
Thank you @Megajin, this is valuableNatty
What if we want to sort by keys which are numbers but in descending order? For example, first '4000', then '3000', '2000'...?Dight
@ivanmilenkovic , that is really easy. The sort() Method can take a function as an argument to compare numbers: function compareNumbers(a, b) { return a - b; } Here is the reference: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Illustration
C
83

It's 2019 and we have a 2019 way to solve this :)

Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())
Cloudberry answered 17/3, 2019 at 15:48 Comment(12)
How do we sort nested objects by key?Sheikh
@a2441918 In the same way as you would do with the sort() function. Have a look: developer.mozilla.org/de/docs/Web/JavaScript/Reference/… Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort((k, j) => k - j))Stir
For TypeScript users this isn't available for us yet, see: github.com/microsoft/TypeScript/issues/30933Acknowledgment
Nice one-liner, but how to sort the keys in a case-insensitive manner?Camargo
@Camargo Use a custom function for sort, something like: ``` Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort(([key1, val1], [key2, val2]) => key1.toLowerCase().localeCompare(key2.toLowerCase()))) ```Cloudberry
This solution is heavy - it converts entries arrays to string. And is not working for arbitrary keys, e.g. Object.entries({ a: 8, ['a,1']: 6 }).sort() -> [ [ 'a,1', 6 ], [ 'a', 8 ] ] Oconner
I had to use a custom sorting function, but this answer worked for mePusillanimous
This will sort entries by casting them to string, if our keys have , characters, the resulting order will be affected. Object.fromEntries(Object.entries({'a.': 1, 'a': 2, 'a,': 234}).sort()) - {a,: 234, a: 2, a.: 1}, at least it will be not ascii orderBrottman
It's not 2019 (please put a reminder to edit your answer every year to match the calendar)Ectoparasite
For anyone looking for a custom sort here's an example - Object.entries({b:3, A:8, a:7, c:1}).sort((a, b) => a[0].localeCompare(b[0]))Ectoparasite
:) To be honest, 5 years later, It's still the best way to sort object entries :)Cloudberry
Calling Object.fromEntries seems to completely rewrite the order of the keys in the object passed to it in Node at least.Milestone
J
38

ES6 - here is the 1 liner

var data = { zIndex:99,
             name:'sravan',
             age:25, 
             position:'architect',
             amount:'100k',
             manager:'mammu' };

console.log(Object.entries(data).sort().reduce( (o,[k,v]) => (o[k]=v,o), {} ));
Jannelle answered 4/4, 2018 at 22:57 Comment(4)
What the heck is this crazy syntax? (o[k] = v, o). Why does this even work, where can I find docs about it? It obviously returns the rightmost parameter, but why?Pulque
@Pulque hereCliff
short function first makes o[k] equals to v and then returns oContractor
This solution is heavy - it converts entries arrays to string. And is not working for arbitrary keys, e.g. Object.entries({ a: 8, ['a,1']: 6 }).sort() -> [ [ 'a,1', 6 ], [ 'a', 8 ] ]Oconner
I
29

This works for me

/**
 * Return an Object sorted by it's Key
 */
var sortObjectByKey = function(obj){
    var keys = [];
    var sorted_obj = {};

    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            keys.push(key);
        }
    }

    // sort keys
    keys.sort();

    // create new array based on Sorted Keys
    jQuery.each(keys, function(i, key){
        sorted_obj[key] = obj[key];
    });

    return sorted_obj;
};
Inquisitorial answered 11/10, 2012 at 7:34 Comment(9)
This is actually the correct answer to the question at hand. For a simplified version using Underscore, see: jsfiddle.net/wPjaQ/1Valet
@Valet No this answer is not correct. It returns a new object, which also has no order.Pernell
@Paulpro in theory it doesn't, in practice it does.Valet
@Valet It doesn't in practice either. There is no such thing as order on an objects keys, so how can you say that in practice this gives you an object in sorted order? It really just gives you back a shallow copy of the object you pass in.Pernell
@Paulpro, did you look at the jsfiddle?Valet
@Valet Yes, I see the same object twice.Pernell
This is super wrong. It might happen to work for now, but will break in a different web browser or different page load in the same browser. Browsers may randomize object keys for security, or as you fill up an object, it will put the values into different memory buckets depending on the keys, which will return a different order. If this happens to work it's just lucky for you.Amoakuh
It also has a needless use of jQuery.Dufrene
As @Amoakuh says, this answer is wrong. It might happen to work in some browsers, but it's never guaranteed. JavaScript object properties are never guaranteed to be ordered. From ECMAScript 5.1 §12.6.4: "The mechanics and order of enumerating the properties is not specified." For more details, see this question: Does JavaScript Guarantee Object Property Order?Chaing
T
24

This is an old question, but taking the cue from Mathias Bynens' answer, I've made a short version to sort the current object, without much overhead.

    Object.keys(unordered).sort().forEach(function(key) {
        var value = unordered[key];
        delete unordered[key];
        unordered[key] = value;
    });

after the code execution, the "unordered" object itself will have the keys alphabetically sorted.

Tonnage answered 14/10, 2015 at 11:47 Comment(1)
Gosh oh gosh. Exactly what I was looking for. When operating on objects, I usually prefer to operate on them by reference, so the solutions that were returning new objects weren't ideal. Thanks so much for this. I owe you a coffee/tea/beer/hug in the afterlife :-PBoaten
H
21

Suppose it could be useful in VisualStudio debugger which shows unordered object properties.

(function(s) {
    var t = {};

    Object.keys(s).sort().forEach(function(k) {
        t[k] = s[k]
    });

    return t
})({
    b: 2,
    a: 1,
    c: 3
});

The same as inline version:

(function(s){var t={};Object.keys(s).sort().forEach(function(k){t[k]=s[k]});return t})({b:2,a:1,c:3})
Headlight answered 6/8, 2013 at 20:35 Comment(1)
Nice! Thank you for this succinct solution.Microbarograph
B
20

Using lodash this will work:

some_map = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }

// perform a function in order of ascending key
_(some_map).keys().sort().each(function (key) {
  var value = some_map[key];
  // do something
});

// or alternatively to build a sorted list
sorted_list = _(some_map).keys().sort().map(function (key) {
  var value = some_map[key];
  // return something that shall become an item in the sorted list
}).value();

Just food for thought.

Blaspheme answered 23/6, 2013 at 13:54 Comment(0)
F
15

I am actually very surprised that over 30 answers were given, and yet none gave a full deep solution for this problem. Some had shallow solution, while others had deep but faulty (it'll crash if undefined, function or symbol will be in the json).

Here is the full solution:

function sortObject(unordered, sortArrays = false) {
  if (!unordered || typeof unordered !== 'object') {
    return unordered;
  }

  if (Array.isArray(unordered)) {
    const newArr = unordered.map((item) => sortObject(item, sortArrays));
    if (sortArrays) {
      newArr.sort();
    }
    return newArr;
  }

  const ordered = {};
  Object.keys(unordered)
    .sort()
    .forEach((key) => {
      ordered[key] = sortObject(unordered[key], sortArrays);
    });
  return ordered;
}

const json = {
  b: 5,
  a: [2, 1],
  d: {
    b: undefined,
    a: null,
    c: false,
    d: true,
    g: '1',
    f: [],
    h: {},
    i: 1n,
    j: () => {},
    k: Symbol('a')
  },
  c: [
    {
      b: 1,
      a: 1
    }
  ]
};
console.log(sortObject(json, true));
Fiertz answered 24/6, 2020 at 10:9 Comment(2)
Same thing for me! I scrolled through to find a deep solution to the problem (before posting my own answer, which was equivalent to yours). But then I saw yours, and upvoted that instead. :)Dell
Your answer is a legit one. +1Prisilla
H
9

Underscore version:

function order(unordered)
{
return _.object(_.sortBy(_.pairs(unordered),function(o){return o[0]}));
}

If you don't trust your browser for keeping the order of the keys, I strongly suggest to rely on a ordered array of key-value paired arrays.

_.sortBy(_.pairs(c),function(o){return o[0]})
Hypersensitive answered 7/6, 2015 at 13:8 Comment(1)
Better: _.object(_.sortBy(_.pairs(unordered), _.first))Coates
C
9
// if keys are char/string
const sortObject = (obj) => Object.fromEntries(Object.entries(obj).sort( ));
let obj = { c: 3, a: 1 };
obj = sortObject(obj)

// if keys are numbers
const sortObject = (obj) => Object.fromEntries(Object.entries(obj).sort( (a,b)=>a-b ));
let obj = { 3: 'c', 1: 'a' };
obj = sortObject(obj)
Chingchinghai answered 26/7, 2021 at 1:25 Comment(0)
D
8

Maybe a bit more elegant form:

 /**
     * Sorts a key-value object by key, maintaining key to data correlations.
     * @param {Object} src  key-value object
     * @returns {Object}
     */
var ksort = function ( src ) {
      var keys = Object.keys( src ),
          target = {};
      keys.sort();
      keys.forEach(function ( key ) {
        target[ key ] = src[ key ];
      });
      return target;
    };


// Usage
console.log(ksort({
  a:1,
  c:3,
  b:2  
}));

P.S. and the same with ES6+ syntax:

function ksort( src ) {
  const keys = Object.keys( src );
  keys.sort();
  return keys.reduce(( target, key ) => {
        target[ key ] = src[ key ];
        return target;
  }, {});
};
Dierdredieresis answered 30/7, 2015 at 13:38 Comment(2)
it's sorts nothing. you still returning an object. you cannot gurantee the objects in your target is actually going to have any order. you need to return an array. jeeezus.Bauer
the only thing you are doing here is ensuring it's a set, in a non optimal way.Bauer
E
8
function sortObjectKeys(obj){
    return Object.keys(obj).sort().reduce((acc,key)=>{
        acc[key]=obj[key];
        return acc;
    },{});
}

sortObjectKeys({
    telephone: '069911234124',
    name: 'Lola',
    access: true,
});
Emalee answered 26/8, 2017 at 16:24 Comment(2)
Maybe adding some explanation of your code is better.Acroter
Gets the keys of the object, so it is array of strings, I sort() them and as it is array of strings (keys) I reduce them (with reduce() of js Array). The acc initially is an empty object {} (last arg of reducer) and the reducer (callback) assigns on the empty object the values of the source obj with the ordered key sequence.Emalee
A
8

Here is a one line solution (not the most efficient but when it comes to thin objects like in your example I'd rather use native JS functions then messing up with sloppy loops)

const unordered = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }

const ordered = Object.fromEntries(Object.entries(unordered).sort())

console.log(ordered); // a->b->c
Aten answered 8/10, 2020 at 13:39 Comment(0)
M
8

const sortObjectByKeys = (object, {desc = false} = {}) => Object.fromEntries(
  Object.entries(object).sort(([k1], [k2]) => k1 < k2 ^ desc ? -1 : 1),
)

const object = { b: 'asdsad', c: 'masdas', a: 'dsfdsfsdf' }

const orderedObject    = sortObjectByKeys(object)
const orderedObjectRev = sortObjectByKeys(object, {desc: true})

console.log({orderedObject, orderedObjectRev})

Or use tiny objectools package:

import o from 'objectools'

o({b: 1, a: 2, c: 3}).sort() // --> {a: 2, b: 1, c: 3}
Michelsen answered 27/6, 2022 at 13:38 Comment(1)
Simply beautiful!Horseback
E
6

recursive sort, for nested object and arrays

function sortObjectKeys(obj){
    return Object.keys(obj).sort().reduce((acc,key)=>{
        if (Array.isArray(obj[key])){
            acc[key]=obj[key].map(sortObjectKeys);
        }
        if (typeof obj[key] === 'object'){
            acc[key]=sortObjectKeys(obj[key]);
        }
        else{
            acc[key]=obj[key];
        }
        return acc;
    },{});
}

// test it
sortObjectKeys({
    telephone: '069911234124',
    name: 'Lola',
    access: true,
    cars: [
        {name: 'Family', brand: 'Volvo', cc:1600},
        {
            name: 'City', brand: 'VW', cc:1200, 
            interior: {
                wheel: 'plastic',
                radio: 'blaupunkt'
            }
        },
        {
            cc:2600, name: 'Killer', brand: 'Plymouth',
            interior: {
                wheel: 'wooden',
                radio: 'earache!'
            }
        },
    ]
});
Emalee answered 26/8, 2017 at 16:38 Comment(5)
I think you need an else in there -- could be true for both Array.isArray(obj[key]) and for typeof obj[key] === 'object'Guillermo
When you have an array of primitives, your function transforms the primitives (string/number) to empty objects. To catch this I added the following right at the beginning of your function: function sortObjectKeys(obj){: if(typeof obj != 'object'){ /* it is a primitive: number/string (in an array) */ return obj; }. For robustness I at the complete start also added: if(obj == null || obj == undefined){ return obj; }Landan
var sortKeys = (unordered) => { function srt(obj){ const isAr = Array.isArray(obj) return !isAr && typeof obj === 'object' ? Object.keys(obj).sort().reduce((a,k)=>{ let vl = obj[k] let isArr = Array.isArray(vl) if (isArr) vl = vl.map(srt) if (vl && typeof vl === 'object' && !isArr) a[k]=srt(vl) else a[k]=vl return a; },{}) : (isAr ? obj.map(srt) : obj); } console.log(JSON.stringify(srt(unordered), null, 4)) }Joviality
Above can help to preserve array, as well in your solution, array is getting converted to array-like objectJoviality
This solution can convert arrays to objects in some cases. (eg. array within an array)Dell
K
5

Here is a clean lodash-based version that works with nested objects

/**
 * Sort of the keys of an object alphabetically
 */
const sortKeys = function(obj) {
  if(_.isArray(obj)) {
    return obj.map(sortKeys);
  }
  if(_.isObject(obj)) {
    return _.fromPairs(_.keys(obj).sort().map(key => [key, sortKeys(obj[key])]));
  }
  return obj;
};

It would be even cleaner if lodash had a toObject() method...

Kernel answered 10/11, 2016 at 17:42 Comment(0)
S
5

There's a great project by @sindresorhus called sort-keys that works awesome.

You can check its source code here:

https://github.com/sindresorhus/sort-keys

Or you can use it with npm:

$ npm install --save sort-keys

Here are also code examples from his readme

const sortKeys = require('sort-keys');

sortKeys({c: 0, a: 0, b: 0});
//=> {a: 0, b: 0, c: 0}

sortKeys({b: {b: 0, a: 0}, a: 0}, {deep: true});
//=> {a: 0, b: {a: 0, b: 0}}

sortKeys({c: 0, a: 0, b: 0}, {
    compare: (a, b) => -a.localeCompare(b)
});
//=> {c: 0, b: 0, a: 0}
Soak answered 6/4, 2017 at 23:22 Comment(0)
W
5
Object.keys(unordered).sort().reduce(
    (acc,curr) => ({...acc, [curr]:unordered[curr]})
    , {}
)
Waw answered 15/7, 2019 at 13:41 Comment(2)
This could fit on one-line here on SO if you didn't break it for clarity, and for a one-liner in a sea of loops, this deserves more credit. Nice use of the spread operator to merge, I've always done it the same way, but assigned and then returned, so have learned something with solution :)Tied
How can I remove the error in typescript: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '..Panhandle
T
5

This works as of Jan 2023

var obj = {
'b':'cVal',
'a':'aVal',
'c':'bVal'
}
console.log(JSON.stringify(obj))
obj = Object.fromEntries(Object.entries(obj).sort())
console.log(JSON.stringify(obj));
Thunell answered 3/1, 2023 at 4:58 Comment(0)
D
4

Use this code if you have nested objects or if you have nested array obj.

var sortObjectByKey = function(obj){
    var keys = [];
    var sorted_obj = {};
    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            keys.push(key);
        }
    }
    // sort keys
    keys.sort();

    // create new array based on Sorted Keys
    jQuery.each(keys, function(i, key){
        var val = obj[key];
        if(val instanceof Array){
            //do for loop;
            var arr = [];
            jQuery.each(val,function(){
                arr.push(sortObjectByKey(this));
            }); 
            val = arr;

        }else if(val instanceof Object){
            val = sortObjectByKey(val)
        }
        sorted_obj[key] = val;
    });
    return sorted_obj;
};
Daberath answered 25/2, 2014 at 14:30 Comment(2)
The author doesn't state say that he is using jQuery, nor is the question tagged jQuery. It would be nice if you addes a solution in pure javascript.Nightclub
Thanks @Phani this is exactly what I neededRelief
L
4

As already mentioned, objects are unordered.

However...

You may find this idiom useful:

var o = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' };

var kv = [];

for (var k in o) {
  kv.push([k, o[k]]);
}

kv.sort()

You can then iterate through kv and do whatever you wish.

> kv.sort()
[ [ 'a', 'dsfdsfsdf' ],
  [ 'b', 'asdsad' ],
  [ 'c', 'masdas' ] ]
Liturgical answered 29/10, 2014 at 16:32 Comment(1)
In reality and in ES6 objects are ordered.Bialy
H
3

Just use lodash to unzip map and sortBy first value of pair and zip again it will return sorted key.

If you want sortby value change pair index to 1 instead of 0

var o = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' };
console.log(_(o).toPairs().sortBy(0).fromPairs().value())

enter image description here

Huysmans answered 10/1, 2017 at 19:23 Comment(1)
Please use the edit link explain how this code works and don't just give the code, as an explanation is more likely to help future readers. See also How to Answer. sourceGerge
S
3

Sorts keys recursively while preserving references.

function sortKeys(o){
    if(o && o.constructor === Array)
        o.forEach(i=>sortKeys(i));
    else if(o && o.constructor === Object)
        Object.entries(o).sort((a,b)=>a[0]>b[0]?1:-1).forEach(e=>{
            sortKeys(e[1]);
            delete o[e[0]];
            o[e[0]] = e[1];
        });
}

Example:

let x = {d:3, c:{g:20, a:[3,2,{s:200, a:100}]}, a:1};
let y = x.c;
let z = x.c.a[2];
sortKeys(x);
console.log(x); // {a: 1, c: {a: [3, 2, {a: 1, s: 2}], g: 2}, d: 3}
console.log(y); // {a: [3, 2, {a: 100, s: 200}}, g: 20}
console.log(z); // {a: 100, s: 200}
Sweyn answered 23/7, 2018 at 15:33 Comment(4)
Nice snippet! What's the purpose of delete o[e[0]]; there? Can't we just assign?Hypnotize
It seems like only new assignments to non existent keys will append the key at the end. If delete is commented out, keys wont be sorted, at least not in Chrome.Sweyn
that makes sense. Thanks! In any case, this is sort of a lost cause because js object keys have no sequence, according to the specs. We are just exploiting obj and log function impl detailsHypnotize
Yea, I use the Map when order of keys are important: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Sweyn
J
3

This is a lightweight solution to everything I need for JSON sorting.

function sortObj(obj) {
    if (typeof obj !== "object" || obj === null)
        return obj;

    if (Array.isArray(obj))
        return obj.map((e) => sortObj(e)).sort();

    return Object.keys(obj).sort().reduce((sorted, k) => {
        sorted[k] = sortObj(obj[k]);
        return sorted;
    }, {});
}
Jacintha answered 17/10, 2019 at 22:33 Comment(1)
Caution: This sorts not just keys, but also array items!Dell
B
2

Solution:

function getSortedObject(object) {
  var sortedObject = {};

  var keys = Object.keys(object);
  keys.sort();

  for (var i = 0, size = keys.length; i < size; i++) {
    key = keys[i];
    value = object[key];
    sortedObject[key] = value;
  }

  return sortedObject;
}

// Test run
getSortedObject({d: 4, a: 1, b: 2, c: 3});

Explanation:

Many JavaScript runtimes store values inside an object in the order in which they are added.

To sort the properties of an object by their keys you can make use of the Object.keys function which will return an array of keys. The array of keys can then be sorted by the Array.prototype.sort() method which sorts the elements of an array in place (no need to assign them to a new variable).

Once the keys are sorted you can start using them one-by-one to access the contents of the old object to fill a new object (which is now sorted).

Below is an example of the procedure (you can test it in your targeted browsers):

/**
 * Returns a copy of an object, which is ordered by the keys of the original object.
 *
 * @param {Object} object - The original object.
 * @returns {Object} Copy of the original object sorted by keys.
 */
function getSortedObject(object) {
  // New object which will be returned with sorted keys
  var sortedObject = {};

  // Get array of keys from the old/current object
  var keys = Object.keys(object);
  // Sort keys (in place)
  keys.sort();

  // Use sorted keys to copy values from old object to the new one
  for (var i = 0, size = keys.length; i < size; i++) {
    key = keys[i];
    value = object[key];
    sortedObject[key] = value;
  }

  // Return the new object
  return sortedObject;
}

/**
 * Test run
 */
var unsortedObject = {
  d: 4,
  a: 1,
  b: 2,
  c: 3
};

var sortedObject = getSortedObject(unsortedObject);

for (var key in sortedObject) {
  var text = "Key: " + key + ", Value: " + sortedObject[key];
  var paragraph = document.createElement('p');
  paragraph.textContent = text;
  document.body.appendChild(paragraph);
}

Note: Object.keys is an ECMAScript 5.1 method but here is a polyfill for older browsers:

if (!Object.keys) {
  Object.keys = function (object) {
    var key = [];
    var property = undefined;
    for (property in object) {
      if (Object.prototype.hasOwnProperty.call(object, property)) {
        key.push(property);
      }
    }
    return key;
  };
}
Biathlon answered 6/7, 2015 at 21:55 Comment(0)
S
2

Simple and readable snippet, using lodash.

You need to put the key in quotes only when calling sortBy. It doesn't have to be in quotes in the data itself.

_.sortBy(myObj, "key")

Also, your second parameter to map is wrong. It should be a function, but using pluck is easier.

_.map( _.sortBy(myObj, "key") , "value");
Superbomb answered 14/7, 2015 at 3:16 Comment(1)
_.sortBy(myObj, "key") will sort the collection by a key belonging to the collection items (I.e. myObj.item.key) rather than the myObj itself (myObj.item where 'item' is an object).Ambiguity
S
2

I transfered some Java enums to javascript objects.

These objects returned correct arrays for me. if object keys are mixed type (string, int, char), there is a problem.

var Helper = {
    isEmpty: function (obj) {
        return !obj || obj === null || obj === undefined || Array.isArray(obj) && obj.length === 0;
    },

    isObject: function (obj) {
        return (typeof obj === 'object');
    },

    sortObjectKeys: function (object) {
        return Object.keys(object)
            .sort(function (a, b) {
                c = a - b;
                return c
            });
    },
    containsItem: function (arr, item) {
        if (arr && Array.isArray(arr)) {
            return arr.indexOf(item) > -1;
        } else {
            return arr === item;
        }
    },

    pushArray: function (arr1, arr2) {
        if (arr1 && arr2 && Array.isArray(arr1)) {
            arr1.push.apply(arr1, Array.isArray(arr2) ? arr2 : [arr2]);
        }
    }
};

function TypeHelper() {
    var _types = arguments[0],
        _defTypeIndex = 0,
        _currentType,
        _value;

    if (arguments.length == 2) {
        _defTypeIndex = arguments[1];
    }

    Object.defineProperties(this, {
        Key: {
            get: function () {
                return _currentType;
            },
            set: function (val) {
                _currentType.setType(val, true);
            },
            enumerable: true
        },
        Value: {
            get: function () {
                return _types[_currentType];
            },
            set: function (val) {
                _value.setType(val, false);
            },
            enumerable: true
        }
    });

    this.getAsList = function (keys) {
        var list = [];
        Helper.sortObjectKeys(_types).forEach(function (key, idx, array) {
            if (key && _types[key]) {

                if (!Helper.isEmpty(keys) && Helper.containsItem(keys, key) || Helper.isEmpty(keys)) {
                    var json = {};
                    json.Key = key;
                    json.Value = _types[key];
                    Helper.pushArray(list, json);
                }
            }
        });
        return list;
    };

    this.setType = function (value, isKey) {
        if (!Helper.isEmpty(value)) {
            Object.keys(_types).forEach(function (key, idx, array) {
                if (Helper.isObject(value)) {
                    if (value && value.Key == key) {
                        _currentType = key;
                    }
                } else if (isKey) {
                    if (value && value.toString() == key.toString()) {
                        _currentType = key;
                    }
                } else if (value && value.toString() == _types[key]) {
                    _currentType = key;
                }
            });
        } else {
            this.setDefaultType();
        }
        return isKey ? _types[_currentType] : _currentType;
    };

    this.setTypeByIndex = function (index) {
        var keys = Helper.sortObjectKeys(_types);
        for (var i = 0; i < keys.length; i++) {
            if (index === i) {
                _currentType = keys[index];
                break;
            }
        }
    };

    this.setDefaultType = function () {
        this.setTypeByIndex(_defTypeIndex);
    };

    this.setDefaultType();
}


var TypeA = {
    "-1": "Any",
    "2": "2L",
    "100": "100L",
    "200": "200L",
    "1000": "1000L"
};

var TypeB = {
    "U": "Any",
    "W": "1L",
    "V": "2L",
    "A": "100L",
    "Z": "200L",
    "K": "1000L"
};
console.log('keys of TypeA', Helper.sortObjectKeys(TypeA));//keys of TypeA ["-1", "2", "100", "200", "1000"]

console.log('keys of TypeB', Helper.sortObjectKeys(TypeB));//keys of TypeB ["U", "W", "V", "A", "Z", "K"]

var objectTypeA = new TypeHelper(TypeA),
    objectTypeB = new TypeHelper(TypeB);

console.log('list of objectA = ', objectTypeA.getAsList());
console.log('list of objectB = ', objectTypeB.getAsList());
Types:

var TypeA = {
    "-1": "Any",
    "2": "2L",
    "100": "100L",
    "200": "200L",
    "1000": "1000L"
};

var TypeB = {
    "U": "Any",
    "W": "1L",
    "V": "2L",
    "A": "100L",
    "Z": "200L",
    "K": "1000L"
};


Sorted Keys(output):

Key list of TypeA -> ["-1", "2", "100", "200", "1000"]

Key list of TypeB -> ["U", "W", "V", "A", "Z", "K"]
Spelldown answered 27/8, 2015 at 9:19 Comment(0)
C
2

The one line:

Object.entries(unordered)
  .sort(([keyA], [keyB]) => keyA > keyB)
  .reduce((obj, [key,value]) => Object.assign(obj, {[key]: value}), {})
Calcium answered 16/7, 2019 at 21:32 Comment(0)
B
2

You can sort like this:

Object.fromEntries(Object.entries(obj).sort(([a],[b]) => a.localeCompare(b)))
Bohaty answered 12/2, 2023 at 14:29 Comment(0)
S
1

Pure JavaScript answer to sort an Object. This is the only answer that I know of that will handle negative numbers. This function is for sorting numerical Objects.

Input obj = {1000: {}, -1200: {}, 10000: {}, 200: {}};

function osort(obj) {
var keys = Object.keys(obj);
var len = keys.length;
var rObj = [];
var rK = [];
var t = Object.keys(obj).length;
while(t > rK.length) {
    var l = null;
    for(var x in keys) {
        if(l && parseInt(keys[x]) < parseInt(l)) {
            l = keys[x];
            k = x;
        }
        if(!l) { // Find Lowest
            var l = keys[x];
            var k = x;
        }
    }
    delete keys[k];
    rK.push(l);
}

for (var i = 0; i < len; i++) {

    k = rK[i];
    rObj.push(obj[k]);
}
return rObj;
}

The output will be an object sorted by those numbers with new keys starting at 0.

Schriever answered 15/10, 2015 at 23:35 Comment(0)
S
1

Just to simplify it and make it more clear the answer from Matt Ball

//your object
var myObj = {
    b : 'asdsadfd',
    c : 'masdasaf',
    a : 'dsfdsfsdf'
  };

//fixed code
var keys = [];
for (var k in myObj) {
  if (myObj.hasOwnProperty(k)) {
    keys.push(k);
  }
}
keys.sort();
for (var i = 0; i < keys.length; i++) {
  k = keys[i];
  alert(k + ':' + myObj[k]);
}
Savory answered 3/6, 2017 at 12:17 Comment(0)
B
1

Not sure if this answers the question, but this is what I needed.

Maps.iterate.sorted = function (o, callback) {
    var keys = Object.keys(o), sorted = keys.sort(), k; 
    if ( callback ) {
            var i = -1;
            while( ++i < sorted.length ) {
                    callback(k = sorted[i], o[k] );
            }
    }

    return sorted;
}

Called as :

Maps.iterate.sorted({c:1, b:2, a:100}, function(k, v) { ... } ) 
Bauer answered 27/1, 2019 at 19:11 Comment(0)
V
1

the best way to do it is

 const object =  Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})

 //else if its in reverse just do 

 const object = Object.keys(0).reverse ()

You can first convert your almost-array-like object to a real array, and then use .reverse():

Object.assign([], {1:'banana', 2:'apple', 
3:'orange'}).reverse();
// [ "orange", "apple", "banana", <1 empty slot> ]

The empty slot at the end if cause because your first index is 1 instead of 0. You can remove the empty slot with .length-- or .pop().

Alternatively, if you want to borrow .reverse and call it on the same object, it must be a fully-array-like object. That is, it needs a length property:

Array.prototype.reverse.call({1:'banana', 2:'apple', 
3:'orange', length:4});
// {0:"orange", 1:"apple", 3:"banana", length:4}

Note it will return the same fully-array-like object object, so it won't be a real array. You can then use delete to remove the length property.

Vestibule answered 18/3, 2020 at 21:1 Comment(0)
R
1

i liked this aswer above except it doesnt work:

/**
 * Return an Object sorted by it's Key
 */
var sortObjectByKey = function(obj){
    var keys = [];
    var sorted_obj = {};

    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            keys.push(key);
        }
    }

    // sort keys
    keys.sort();

    // create new array based on Sorted Keys
    jQuery.each(keys, function(i, key){
        sorted_obj[key] = obj[key];
    });

    return sorted_obj;
};

looks like the sorted_obj there isnt guaranty of order, for that map seems to be a better fit, i ended up changing the object for a map, something like this:

/**
 * Return an Object sorted by it's Key
 */
var sortObjectByKey = function(obj){
    var keys = [];
    let sorted_map = new Map();

    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            keys.push(key);
        }
    }

    // sort keys
    keys.sort();

    // create new map based on Sorted Keys
    keys.forEach(key => {
        sorted_map.set(key, obj[key]);
    });

    return sorted_map;
};
Rinarinaldi answered 30/8, 2021 at 20:58 Comment(1)
Is there a reason why didn't you use Object.keys(obj) instead of for(var key in obj){ if(obj.hasOwnProperty(key)){ keys.push(key); }} ?Pusillanimous
D
0

The selected answer doesn't consider nested json object case.

To sort an object with nested children by key, you need recursively sorts the object:

function sortObjectByKeyDeep(obj) {
  const sortedObj = {};
  const keys = Object.keys(obj).sort();

  for (let i = 0; i < keys.length; i++) {
    const key = keys[i];
    const value = obj[key];

    if (typeof value === "object" && !Array.isArray(value)) {
      sortedObj[key] = sortObjectByKeyDeep(value);
    } else if (Array.isArray(value)) {
      sortedObj[key] = value.map((item) =>
        typeof item === "object" ? sortObjectByKeyDeep(item) : item
      );
    } else {
      sortedObj[key] = value;
    }
  }

  return sortedObj;
}

Test case:

const myObj = {
  c: 1,
  b: {
    d: 2,
    a: 3,
  },
  e: [
    {
      g: 4,
      f: 5,
    },
    {
      i: 6,
      h: 7,
    },
  ],
};

const sortedObj = sortObjectByKeyDeep(myObj);
console.log(sortedObj);
// Output: {b: {a: 3, d: 2}, c: 1, e: [{f: 5, g: 4}, {h: 7, i: 6}]}
Despair answered 3/5, 2023 at 15:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.