简体   繁体   English

按键排序 JavaScript object

[英]Sort JavaScript object by key

I need to sort JavaScript objects by key.我需要按键对 JavaScript 个对象进行排序。

Hence the following:因此如下:

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

Would become:会成为:

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

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.这个问题的其他答案已经过时,与实现现实不匹配,并且在 ES6 / ES2015 规范发布后正式变得不正确。


See the section on property iteration order in Exploring ES6 by Axel Rauschmayer :请参阅Axel Rauschmayer 的Exploring ES6中关于属性迭代顺序的部分

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.所以是的,JavaScript 对象实际上是有序的,并且它们的键/属性的顺序是可以改变的。

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.使用var而不是const以与 ES5 引擎兼容。

JavaScript objects 1 are not ordered. JavaScript 对象1没有排序。 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:使用Object.keys的替代实现:

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


1 Not to be pedantic, but there's no such thing as a JSON object . 1不要迂腐,但不存在 JSON 对象之类的东西

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:而且我认为我们可以再添加一种解决方案——ES5 函数式方式:

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"):上面的 ES2015 版本(格式化为“单线”):

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. Object.keys为我们提供了提供的对象( objo )中的键列表,然后我们使用默认排序算法对它们进行排序,接下来.reduce用于将该数组转换回对象,但这次使用所有排序的键。

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.由于是 2018 年,我将只使用 ES6,所有 Polyfill 都可以在 MDN 文档中找到,我将在给定部分链接。


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:如果您的键只是数字,那么您可以安全地使用Object.keys()Array.prototype.reduce()来返回排序后的对象:

// 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:但是,如果您使用的是字符串,我强烈建议您将Array.prototype.sort()链接到所有这些中:

// 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:如果有人想知道 reduce 的作用:

// 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:简而言之, Object.keys()将返回一个与我们在正常循环中得到的顺序相同的数组:

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. Object.keys() 返回一个数组,其元素是与直接在对象上找到的可枚举属性相对应的字符串。 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:旁注-您也可以在数组上使用Object.keys() ,请记住将返回索引:

// 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:现在,如果我们在上面的数组上使用Array.prototype.sort() ,输出会发生变化:

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. sort() 方法对数组的元素进行就地排序并返回该数组。 The sort is not necessarily stable.排序不一定是稳定的。 The default sort order is according to string Unicode code points.默认排序顺序是根据字符串 Unicode 代码点。

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.在现实生活中的示例中,如果您同时使用不同的信息输入(如 API 和数据库),人们往往会特别混淆事物。


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.稳定排序算法根据以下规则选择其中之一:如果两个项目比较相等,例如两张 5 卡,那么它们的相对顺序将被保留,因此如果输入中一个在另一个之前,它也会在输出中排在另一个之前。

在此处输入图像描述

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.当卡片以稳定排序按等级排序时,两个 5 在它们原来所在的排序输出中必须保持相同的顺序。当它们以非稳定排序排序时,5 可能以相反的顺序结束排序输出中的顺序。

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有关更多 JavaScript 示例,请查看 Array.prototype.sort() - 文档: https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

现在是 2019 年,我们有 2019 年的方法来解决这个问题:)

Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())

ES6 - here is the 1 liner ES6 - 这是 1 班轮

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

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

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.这是一个老问题,但从 Mathias Bynens 的回答中得到启发,我制作了一个简短版本来对当前对象进行排序,没有太多开销。

    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.代码执行后,“无序”对象本身将按字母顺序对键进行排序。

Using lodash this will work:使用 lodash 这将起作用:

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.只是思考的食物。

Suppose it could be useful in VisualStudio debugger which shows unordered object properties.假设它在显示无序对象属性的 VisualStudio 调试器中可能很有用。

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

I am actually very surprised that over 30 answers were given, and yet none gave a full deep solution for this problem.实际上,我很惊讶给出了 30 多个答案,但没有一个为这个问题提供完整的深度解决方案。 Some had shallow solution, while others had deep but faulty (it'll crash if undefined, function or symbol will be in the json).有些解决方案很浅,而另一些解决方案很深但有问题(如果未定义,函数或符号将在 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));

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

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

PS and the same with ES6+ syntax: PS 和 ES6+ 语法相同:

function ksort( src ) {
  const keys = Object.keys( src );
  keys.sort();
  return keys.reduce(( target, key ) => {
        target[ key ] = src[ key ];
        return target;
  }, {});
};
function sortObjectKeys(obj){
    return Object.keys(obj).sort().reduce((acc,key)=>{
        acc[key]=obj[key];
        return acc;
    },{});
}

sortObjectKeys({
    telephone: '069911234124',
    name: 'Lola',
    access: true,
});

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)这是一个单行解决方案(不是最有效的,但是当涉及到像您的示例中那样的瘦对象时,我宁愿使用本机 JS 函数,然后搞乱草率的循环)

 const unordered = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' } const ordered = Object.fromEntries(Object.entries(unordered).sort()) console.log(ordered); // a->b->c

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

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

Here is a clean lodash-based version that works with nested objects这是一个基于 lodash 的干净版本,适用于嵌套对象

/**
 * 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 ...如果 lodash 有一个toObject()方法会更干净......

Object.keys(unordered).sort().reduce(
    (acc,curr) => ({...acc, [curr]:unordered[curr]})
    , {}
)

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 并做任何您想做的事情。

> kv.sort()
[ [ 'a', 'dsfdsfsdf' ],
  [ 'b', 'asdsad' ],
  [ 'c', 'masdas' ] ]

There's a great project by @sindresorhus called sort-keys that works awesome. @sindresorhus 有一个很棒的项目,叫做 sort-keys,非常棒。

You can check its source code here:你可以在这里查看它的源代码:

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

Or you can use it with npm:或者你可以将它与 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}

Use this code if you have nested objects or if you have nested array obj.如果您有嵌套对象或嵌套数组 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;
};

Just use lodash to unzip map and sortBy first value of pair and zip again it will return sorted key.只需使用 lodash 解压缩 map 和 sortBy 对的第一个值并再次 zip 它将返回排序键。

If you want sortby value change pair index to 1 instead of 0如果您希望 sortby 值将对索引更改为1而不是0

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

在此处输入图像描述

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}

This is a lightweight solution to everything I need for JSON sorting.这是我对 JSON 排序所需的一切的轻量级解决方案。

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

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.许多 JavaScript 运行时按照添加的顺序将值存储在对象中。

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.要按对象的键对对象的属性进行排序,您可以使用Object.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).然后可以通过Array.prototype.sort()方法对键数组进行排序,该方法对数组的元素进行就地排序(无需将它们分配给新变量)。

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:注意: Object.keys是 ECMAScript 5.1 方法,但这里是旧浏览器的 polyfill:

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

I transfered some Java enums to javascript objects.我将一些 Java 枚举转移到 javascript 对象。

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

The one line:一行:

Object.entries(unordered)
  .sort(([keyA], [keyB]) => keyA > keyB)
  .reduce((obj, [key,value]) => Object.assign(obj, {[key]: value}), {})

Simple and readable snippet, using lodash.简单易读的代码片段,使用 lodash。

You need to put the key in quotes only when calling sortBy.只有在调用 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.它应该是一个函数,但使用 pluck 更容易。

_.map( _.sortBy(myObj, "key") , "value");

Pure JavaScript answer to sort an Object.对对象进行排序的纯 JavaScript 答案。 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: {}};输入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.输出将是一个按这些数字排序的对象,新键从 0 开始。

Just to simplify it and make it more clear the answer from Matt Ball只是为了简化它并使 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]); }

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) { ... } ) 

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():您可以先将几乎类似数组的对象转换为真正的数组,然后使用 .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().最后的空槽如果因为您的第一个索引是 1 而不是 0 而导致。您可以使用 .length-- 或 .pop() 删除空槽。

Alternatively, if you want to borrow .reverse and call it on the same object, it must be a fully-array-like object.或者,如果你想借用 .reverse 并在同一个对象上调用它,它必须是一个完全类似数组的对象。 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.然后,您可以使用 delete 删除长度属性。

i liked this aswer above except it doesnt work:我喜欢上面的这个 aswer,但它不起作用:

/**
 * 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:看起来 sorted_obj 没有顺序保证,因为该地图似乎更合适,我最终更改了地图的对象,如下所示:

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

 const sortObjectByKeys = (object) => Object.fromEntries( Object.entries(object).sort(([k1], [k2]) => k1 < k2 ? -1 : 1) ) const object = {b: 'asdsad', c: 'masdas', a: 'dsfdsfsdf' } const orderedObject = sortObjectByKeys(object) console.log(orderedObject)

This question comes up when searching for how to sort an object in Typescript as well, so adding here what worked for me.当搜索如何在 Typescript 中对对象进行排序时也会出现这个问题,所以在这里添加对我有用的东西。

With typescript, I was having trouble generalizing the types with the reduce approach.使用 typescript,我在使用reduce方法泛化类型时遇到了麻烦。 Here's what I ended up doing:这就是我最终做的事情:

function sortObject<T>(obj: T, compareFn?: ((a: unknown, b: unknown) => number)) {
    let keys: unknown[];

    if (compareFn) {
        keys = Object.keys(obj).sort(compareFn);
    } else {
        keys = Object.keys(obj).sort();
    }

    // Storing the data in temp object and deleting from the original
    const temp = {} as typeof obj;

    for (let i = 0; i < keys.length; ++i) {
        const typedKey = keys[i] as keyof typeof obj;
        temp[typedKey] = obj[typedKey];
        delete obj[typedKey];
    }

    // Restore the data in sorted order back into the original object
    for (let i = 0; i < keys.length; ++i) {
        const typedKey = keys[i] as keyof typeof obj;
        obj[typedKey] = temp[typedKey];
    }

    return obj;
}

This works as of Jan 2023这从2023 年 1 月起有效

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM