按键对 JavaScript 对象进行排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5467129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sort JavaScript object by key
提问by vdh_ant
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' }
回答by Mathias Bynens
The other answers to this question are outdated, never matched implementation reality, and have officiallybecome incorrect now that the ES6/ES2015 spec has been published.
这个问题的其他答案已经过时,从未符合实现现实,并且现在 ES6/ES2015 规范已经发布,正式变得不正确。
See the section on property iteration orderin Exploring ES6by Axel Rauschmayer:
请参见上一节物业迭代顺序在探索ES6属于Axel Rauschmayer先生:
All methods that iterate over property keys do so in the same order:
- First all Array indices, sorted numerically.
- Then all string keys (that are not indices), in the order in which they were created.
- Then all symbols, in the order in which they were created.
所有迭代属性键的方法都以相同的顺序执行:
- 首先是所有数组索引,按数字排序。
- 然后是所有字符串键(不是索引),按照它们的创建顺序。
- 然后是所有符号,按照它们的创建顺序。
So yes, JavaScript objects arein 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().forEach(function(key) {
ordered[key] = unordered[key];
});
console.log(JSON.stringify(ordered));
// → '{"a":"baz","b":"foo","c":"bar"}'
Use var
instead of const
for compatibility with ES5 engines.
使用var
而不是const
为了与 ES5 引擎兼容。
回答by Matt Ball
JavaScript objects1are 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:
JavaScript 对象1未排序。试图“排序”它们是没有意义的。如果要遍历对象的属性,可以对键进行排序,然后检索关联的值:
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]);
}
1Not to be pedantic, but there's no such thing as a JSON object.
1不要学究气,但没有 JSON 对象这样的东西。
回答by codename-
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 以上版本(格式为“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.
Object.keys
正在给我们提供的对象(obj
或o
)中的键列表,然后我们使用默认排序算法对它们进行排序,next.reduce
用于将该数组转换回对象,但这次所有键都已排序。
回答by Megajin
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,Polyfills 都可以在 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()
withArray.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.
,{}
);
- Docs for reduce: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
- Why use parenthesis on JavaScript return statements: http://jamesknelson.com/javascript-return-parenthesis/
- 减少文档:https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
- 为什么在 JavaScript 返回语句上使用括号:http: //jamesknelson.com/javascript-return-parenthesis/
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. The ordering of the properties is the same as that given by looping over the properties of the object manually.
Object.keys() 返回一个数组,其元素是与直接在对象上找到的可枚举属性相对应的字符串。属性的顺序与通过手动循环对象的属性给出的顺序相同。
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. 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.
sort() 方法就地对数组的元素进行排序并返回数组。排序不一定稳定。默认排序顺序是根据字符串 Unicode 代码点。
排序的时间和空间复杂度无法保证,因为它取决于实现。
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 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.
所以基本上我们的旧数组将被覆盖!如果出于其他原因要保留旧数组,这很重要。所以请记住这一点。
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
回答by Ashit Vora
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;
};
回答by Ben
It's 2019 and we have a 2019 way to solve this :)
现在是 2019 年,我们有 2019 年的方法来解决这个问题:)
Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())
回答by sravan ganji
here is the 1 liner
这是 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), {} ));
回答by Sergio Moura
This is an old question, but taking the cue from Mathias Bynens' answer, I've made a short version to sort the currentobject, 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.
代码执行后,“无序”对象本身将按字母顺序排列键。
回答by Brian M. Hunt
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.
只是深思熟虑。
回答by Serg
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})