vdh*_*ant 456 javascript sorting
我需要按键对JavaScript对象进行排序.
因此如下:
{ 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }
Run Code Online (Sandbox Code Playgroud)
会成为:
{ 'a' : 'dsfdsfsdf', 'b' : 'asdsad', 'c' : 'masdas' }
Run Code Online (Sandbox Code Playgroud)
Mat*_*ens 403
这个问题的其他答案已经过时,从未与实现现实相匹配,并且在ES6/ES2015规范发布后正式变得不正确.
请参见上一节物业迭代顺序在探索ES6属于Axel Rauschmayer先生:
迭代属性键的所有方法都以相同的顺序执行:
- 首先是所有数组索引,按数字排序.
- 然后是所有字符串键(不是索引),按创建顺序排列.
- 然后是所有符号,按创建顺序排列.
所以,是的,JavaScript对象是其实有序,和其密钥/属性的顺序是可以改变的.
以下是按字母顺序按键/属性对对象进行排序的方法:
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"}'
Run Code Online (Sandbox Code Playgroud)
使用var
而不是const
与ES5引擎兼容.
Mat*_*all 238
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]);
}
Run Code Online (Sandbox Code Playgroud)
使用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]);
}
Run Code Online (Sandbox Code Playgroud)
1不要迂腐,但不存在JSON对象.
cod*_*me- 144
很多人都提到"对象无法排序",但之后他们会给你一个有效的解决方案.悖论,不是吗?
没人提到为什么这些解决方案有效.它们是,因为在大多数浏览器的实现中,对象中的值按照添加顺序存储.这就是为什么如果你从排序的键列表中创建新对象,它将返回预期的结果.
而且我认为我们可以再增加一个解决方案 - ES5功能方式:
function sortObject(obj) {
return Object.keys(obj).sort().reduce(function (result, key) {
result[key] = obj[key];
return result;
}, {});
}
Run Code Online (Sandbox Code Playgroud)
ES2015以上版本(格式化为"one-liner"):
function sortObject(o) {
return Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {});
}
Run Code Online (Sandbox Code Playgroud)
上述例子的简短解释(如评论中所述):
Object.keys
给我们提供了一个提供对象(obj
或o
)的键列表,然后我们使用默认排序算法对它们进行排序,接下来.reduce
用于将该数组转换回一个对象,但这次将所有键排序.
Meg*_*jin 50
伙计们,我比喻感到震惊!当然所有答案都有些陈旧,但没有人甚至提到排序的稳定性!所以请耐心等待,我会尽力回答这个问题并详细介绍.所以我现在要道歉,现在阅读会很多.
由于它是2018年我将只使用ES6,Polyfills都可以在MDN文档中找到,我将在给定的部分链接.
回答问题:
如果您的密钥只是数字,那么您可以安全地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), {}));
Run Code Online (Sandbox Code Playgroud)
但是,如果你正在使用字符串,我强烈建议链接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), {}));
Run Code Online (Sandbox Code Playgroud)
如果有人想知道减少了什么:
// 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().
}, {});
Run Code Online (Sandbox Code Playgroud)
如果需要,这里是一个班轮的解释:
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.
,{}
);
Run Code Online (Sandbox Code Playgroud)
为什么排序有点复杂:
简而言之,Object.keys()
将返回一个与正常循环相同顺序的数组:
const object1 = {
a: 'somestring',
b: 42,
c: false
};
console.log(Object.keys(object1));
// expected output: Array ["a", "b", "c"]
Run Code Online (Sandbox Code Playgroud)
Object.keys()返回一个数组,其元素是与直接在对象上找到的可枚举属性相对应的字符串.属性的顺序与手动循环对象的属性所给出的顺序相同.
旁注 - 您也可以Object.keys()
在数组上使用,请记住将返回索引:
// simple array
const arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']
Run Code Online (Sandbox Code Playgroud)
但是这些例子并不那么容易,现实世界的对象可能包含数字和字母字符甚至符号(请不要这样做).
以下是一个示例,其中所有这些都在一个对象中:
// 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' ]
Run Code Online (Sandbox Code Playgroud)
现在,如果我们Array.prototype.sort()
在数组上面使用输出更改:
console.log(Object.keys(testObj).sort());
// output: [ '#01010101010', '1000', '1asc', '2', 'b' ]
Run Code Online (Sandbox Code Playgroud)
以下是文档的引用:
sort()方法对数组中的元素进行排序并返回数组.排序不一定稳定.默认排序顺序是根据字符串Unicode代码点.
由于它取决于实现,因此无法保证排序的时间和空间复杂性.
您必须确保其中一个为您返回所需的输出.在reallife示例中,如果您使用不同的信息输入(如API和数据库),人们往往会混淆一些事情.
那有什么大不了的?
那么每个程序员都应该理解两篇文章:
就地算法:
在计算机科学中,就地算法是一种使用无辅助数据结构来转换输入的算法.但是,辅助变量允许少量额外存储空间.输出通常在算法执行时被输出覆盖.就地算法仅通过替换或交换元素来更新输入序列.非就地的算法有时被称为非就地或不合适的.
所以基本上我们的旧阵列将被覆盖!如果您因其他原因想要保留旧数组,这一点很重要.所以记住这一点.
稳定的排序算法按照它们在输入中出现的顺序对相同的元素进行排序.在对某些类型的数据进行排序时,在确定排序顺序时仅检查部分数据.例如,在右边的卡片分类示例中,卡片按其等级排序,并且忽略了它们的套装.这允许原始列表的多个不同的正确排序版本的可能性.稳定的排序算法根据以下规则选择其中之一:如果两个项目比较相同,如两个5卡,那么它们的相对顺序将被保留,因此如果一个在输入中位于另一个之前,它也将在输出中来到另一个之前.
扑克牌稳定排序的一个例子.当卡按排名按稳定排序排序时,两个5s必须在它们最初所在的排序输出中保持相同的顺序.当它们以非稳定排序排序时,5s可能最终排在相反的位置在排序的输出中排序.
这表明排序是正确的,但它改变了.因此,在现实世界中,即使排序正确,我们也必须确保获得我们期望的结果!这一点非常重要,请记住这一点.有关更多JavaScript示例,请查看Array.prototype.sort() - docs:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Ash*_*ora 28
这适合我
/**
* 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;
};
Run Code Online (Sandbox Code Playgroud)
sra*_*nji 20
这是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), {} ));
Run Code Online (Sandbox Code Playgroud)
Ser*_*ura 19
这是一个老问题,但是从Mathias Bynens的回答中得到提示,我已经制作了一个简短版本来对当前对象进行排序,而没有太多开销.
Object.keys(unordered).sort().forEach(function(key) {
var value = unordered[key];
delete unordered[key];
unordered[key] = value;
});
Run Code Online (Sandbox Code Playgroud)
在代码执行之后,"无序"对象本身将按字母顺序排序.
Ben*_*Ben 17
现在是2019年,我们有一种解决这个问题的2019年方法:)
Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())
Run Code Online (Sandbox Code Playgroud)
Bri*_*unt 16
使用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();
Run Code Online (Sandbox Code Playgroud)
只是值得深思.
小智 15
假设它在VisualStudio调试器中有用,它显示无序对象属性.
(function(s){var t={};Object.keys(s).sort().forEach(function(k){t[k]=s[k]});return t})({b:2,a:1,c:3})
Run Code Online (Sandbox Code Playgroud)
Shl*_*Shl 11
我真的很惊讶给出了 30 多个答案,但没有一个给出了这个问题的完整深度解决方案。有些解决方案很浅,而另一些解决方案很深但有缺陷(如果未定义,函数或符号将在 json 中,它会崩溃)。
这是完整的解决方案:
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));
Run Code Online (Sandbox Code Playgroud)
function order(unordered)
{
return _.object(_.sortBy(_.pairs(unordered),function(o){return o[0]}));
}
Run Code Online (Sandbox Code Playgroud)
如果你不相信你的浏览器保持密钥的顺序,我强烈建议依赖一个有序的键值配对数组.
_.sortBy(_.pairs(c),function(o){return o[0]})
Run Code Online (Sandbox Code Playgroud)
// 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)
Run Code Online (Sandbox Code Playgroud)
也许更优雅的形式:
/**
* 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
}));
Run Code Online (Sandbox Code Playgroud)
PS和ES6 +语法相同:
function ksort( src ) {
const keys = Object.keys( src );
keys.sort();
return keys.reduce(( target, key ) => {
target[ key ] = src[ key ];
return target;
}, {});
};
Run Code Online (Sandbox Code Playgroud)
小智 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,
});
Run Code Online (Sandbox Code Playgroud)
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})
Run Code Online (Sandbox Code Playgroud)
objectools
小包:import o from 'objectools'
o({b: 1, a: 2, c: 3}).sort() // --> {a: 2, b: 1, c: 3}
Run Code Online (Sandbox Code Playgroud)
小智 7
递归排序,用于嵌套对象和数组
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!'
}
},
]
});
Run Code Online (Sandbox Code Playgroud)
这是一个单行解决方案(不是最有效的,但是当涉及到像您的示例中那样的薄对象时,我宁愿使用本机 JS 函数,然后再使用马虎循环)
const unordered = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }
const ordered = Object.fromEntries(Object.entries(unordered).sort())
console.log(ordered); // a->b->c
Run Code Online (Sandbox Code Playgroud)
这是一个干净的基于 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;
};
Run Code Online (Sandbox Code Playgroud)
如果 lodash 有一个toObject()
方法会更干净......
@sindresorhus 有一个很棒的项目,名为 sort-keys,效果非常棒。
您可以在这里查看其源代码:
https://github.com/sindresorhus/sort-keys
或者你可以将它与 npm 一起使用:
$ npm install --save sort-keys
Run Code Online (Sandbox Code Playgroud)
这里还有他的自述文件中的代码示例
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}
Run Code Online (Sandbox Code Playgroud)
Object.keys(unordered).sort().reduce(
(acc,curr) => ({...acc, [curr]:unordered[curr]})
, {}
)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
467193 次 |
最近记录: |