我需要按键对JavaScript对象进行排序。

以下内容:

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


将成为:

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


评论

用JavaScript对JSON对象进行排序的可能重复项

早在2011年(发布此问题时),ECMAScript规范就表示JavaScript对象没有固有的顺序-观察到的顺序与实现有关,因此无法依赖。但是,事实证明,所有JavaScript引擎都实现了或多或少相同的语义,因此这些引擎现在已在ES6中进行了标准化。结果,以下许多答案以前都是正确的,但现在却不正确。

简而言之,当您需要比较或哈希结果时,请使用排序的字符串化:npmjs.com/package/json-stable-stringify

鉴于对象只是地图或根据您的语言而定的字典,您几乎没有理由这么做。顺便说一句,通常,将它们注入映射中的顺序实际上是它们在串化时所处的顺序。因此,如果您创建了新地图并根据预排序键列表分配了值,您将发现自己基于键的有序地图

请注意,自从将Object.entries和Object.fromEntries添加到JS以来,就可以使用非常短的单行代码来实现:Object.fromEntries(Object.entries(obj).sort())

#1 楼

此问题的其他答案已过时,从未与实现现实相匹配,并且由于ES6 / ES2015规范已发布而正式变得不正确。 Rauschmayer:

所有对属性键进行迭代的方法都以相同的顺序进行操作:

首先对所有Array索引进行数字排序。
然后对所有字符串键(即不是索引),而是按照创建它们的顺序。
然后所有符号,按照它们创建的顺序。


所以是的,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().reduce(
  (obj, key) => ({ obj[key]: unordered[key] }), {}
);

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




使用var而不是const来与ES5引擎兼容。

评论


除了使用稍微不同的循环技术外,我真的看不到您的代码和此处的最佳答案有所不同。物体是否可以说是“有序的”似乎无关紧要。这个问题的答案还是一样。已发布的规范仅在此处确认答案。

–菲尔
15年9月22日在14:44

仅供参考,澄清了属性的枚举顺序仍然不确定:esdiscuss.org/topic/…

–费利克斯·克林(Felix Kling)
2015年12月1日14:41

@ Phil_1984_这个答案和最高投票答案非常不同。 OP的问题是如何对对象文字进行排序。投票最高的答案是您不能这样做,然后给出一种解决方法,将已排序的键存储在数组中,然后从已排序的数组中迭代并打印键值对。该答案声称对象文字的顺序现在可以排序,并且他的示例将排序后的键值存储回对象文字,然后直接打印排序后的对象。附带说明一下,如果链接的站点仍然存在,那就太好了。

–cchamberlain
16年3月14日在5:25

这两个答案都仅使用Array.sort函数首先对键进行排序。 OP要求对“ JavaScript对象”进行排序,并且仅使用JavaScript对象符号(JSON)来描述这两个对象。这两个对象在逻辑上是相同的,意味着排序是不相关的。我认为最佳答案可以更好地说明这一点。对我来说,“所有其他答案现在都正式不正确”对我来说太极端了,尤其是链接断开时。我认为问题在于“此新的ES6规范”给人一种幻觉,即Javascript对象具有键的有序列表,这简直是不正确的。

–菲尔
16 Mar 14 '16 at 25:25

请补充说,各种现代浏览器(Google“ caniuse ES6”)不支持该解决方案。使用此答案仅会冒险在某些浏览器中发现难以发现的错误(例如,当Chrome正常时,使用Safari)。

– Manuel Arwed Schmidt
16年5月2日在12:00

#2 楼

JavaScript objects1不排序。尝试对它们进行“分类”是没有意义的。如果要遍历对象的属性,可以对键进行排序,然后检索关联的值:




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






使用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不必太花哨,但是没有JSON对象之类的东西。

评论


@MarcelKorpel这里有一个JSON对象。检查官方JSON RFC的第8节:ietf.org/rfc/rfc4627.txt

– Paul
13年7月12日在20:02



@Paulpro关于RFC的两点注意事项:首先,它已经存在7年了,词汇随时间而变化;第二,“此备忘录为Internet社区提供信息。它没有指定任何类型的Internet标准。”给定的字符序列表示JavaScript对象文字还是JSON文本取决于上下文/用法。术语“ JSON对象”充斥并以有害的方式使区分变得模棱两可。让我们摆脱不精确的术语,并尽可能使用更精确的术语。我认为没有其他理由。话语很重要。

–马特球
13年7月12日在20:33



@MattBall IMO JSON对象是诸如{“ a”,1}之类的字符串的非常精确的术语,就像JSON Array是诸如[1]之类的字符串的精确术语一样。当您具有字符串[{x:1},{y:2},{z:3}]时,通过说出数组中的第三个对象之类的东西进行交流非常有用,因此我更喜欢“在评论Javascript文字时不是“ JSON对象”,而是“没有JSON对象”,这将在稍后OP实际使用JSON时引起更多的混乱和通信困难。

– Paul
13年7月12日在20:48

@Paulpro我必须不同意。 {“ a”,1}是对象文字或JSON文本(如果您确实喜欢,也称为JSON字符串)。它取决于上下文,前者是否在JavaScript源代码中逐字显示,后者则是需要传递给JSON解析器以进一步使用的字符串。在允许的语法,正确的用法和序列化方面,两者之间确实存在差异。

–马特球
13年7月12日在21:01



既然ES6 / ES2015已经完成,那么这个答案正式变得不正确了。请参阅我的答案以获取更多信息。

–马蒂亚斯·拜恩斯(Mathias Bynens)
15年6月28日在17:24

#3 楼

很多人提到“对象无法排序”,但是之后他们给了您有效的解决方案。悖论,不是吗?

没人提到为什么这些解决方案有效。之所以这样,是因为在大多数浏览器的实现中,对象中的值都是按照添加顺序存储的。这就是为什么如果您从排序的键列表中创建新对象会返回预期结果的原因。
我认为我们可以再添加一个解决方案– ES5功能方式:

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


ES2015以上版本(格式化为“单线”):

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


以上示例的简短说明(如评论中所述) :

Object.keys向我们提供了所提供对象(objo)中的键的列表,然后我们使用默认的排序算法对其进行排序,接下来.reduce用于将该数组转换回对象,但这一次所有键都已排序。

评论


@Pointy此行为在所有主要浏览器中始终可用,并已在ES6 / ES2015中进行了标准化。我想这是个好建议。

–马蒂亚斯·拜恩斯(Mathias Bynens)
15年6月28日在17:26

这是在EcmaScript v5中完成任务的最简单,最简洁的方法。晚会晚了一点,但应该被接受。

–史蒂文·德·萨拉斯(Steven de Salas)
15年7月12日在12:55



“之所以如此,是因为在大多数浏览器的实现中,对象中的值都是按照添加它们的顺序存储的。”但仅适用于非数值属性。还请注意,仍然无法保证按顺序迭代属性(例如,通过for ... in)。

–费利克斯·克林(Felix Kling)
16-2-18在16:17



你们很高兴向您解释为什么它起作用了。谢谢!

–ola
17年4月2日在17:06

我的小子抱怨这条线(返回任务),但是这一条对我有用,对我来说更容易阅读:Object.keys(dict).sort()。reduce((r,k)=> Object。 Assign(r,{[k]:dict [k]}),{});

– aks。
17年6月22日在22:48



#4 楼

伙计们,我很震惊!当然,所有答案都有些陈旧,但没人能提及排序的稳定性!因此,请允许我尽力回答问题本身,并在此处进行详细说明。所以我要道歉,现在要阅读很多。

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


但是,如果您使用的是字符串,我强烈建议将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), {}));


如果有人想知道减少量是怎么做的:

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


如果需要,这里是对一根衬管的说明:

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



减少文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

为什么在括号上使用括号JavaScript返回语句:http://jamesknelson.com/javascript-return-parenthesis/



为什么排序有点复杂:

在简短的Object.keys()将返回具有与正常循环相同顺序的数组:

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

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



Object.keys()返回其元素为字符串
与直接在对象上找到的可枚举属性相对应。
属性的顺序与手动遍历对象的属性所赋予的顺序相同。



https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

Sidenote-您可以使用在数组上也是Object.keys(),请记住将返回索引:

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


但这并不像这些示例所示的那样容易,现实世界中的对象可能包含数字,字母字符甚至符号(请不要这样做)。

这里是一个示例,其中所有示例都包含在其中一个对象:

// 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' ]


现在,如果我们在输出更改上方的阵列上使用Array.prototype.sort(),则:

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


这是来自docs的引文:


sort()方法对数组中的元素进行排序,并返回
数组。排序不一定是稳定的。默认的排序顺序
根据字符串Unicode代码点。

无法保证排序的时间和空间复杂性,因为它
与实现有关。



https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

您必须确保其中之一为您返回所需的输出。在现实生活中,如果您一起使用API​​和数据库等不同的信息输入,人们往往会特别混淆。


那有什么大不了的?

那么,每个程序员都应该了解两篇文章:

就地算法:


在计算机科学中,位置算法是一种不使用辅助数据结构来转换输入的算法。但是,可以为辅助变量保留少量的额外存储空间。算法执行时,输入通常会被输出覆盖。就地算法仅通过元素的替换或交换来更新输入序列。非原位算法有时称为非原位或非原位。


所以基本上我们的旧数组将被覆盖!如果您出于其他原因要保留旧阵列,则这一点很重要。因此请记住这一点。

排序算法


稳定的排序算法以相同的顺序对相同的元素进行排序
它们出现在输入中。在对某些类型的数据进行排序时,在确定排序顺序时仅检查部分数据。例如,在右边卡片排序示例中的
,卡片按其等级进行排序
,而其衣服则被忽略。这允许
原始列表的多个不同正确排序版本的可能性。稳定的排序算法会根据以下规则选择其中一种,
:如果两个项目比较相等,例如
这两个5张牌,则它们的相对顺序将被保留,因此
一个在输入中先于另一个,也将在输出中先于另一个。





稳定排序的示例。当卡片按等级排序并具有稳定的排序时,两个5在原始输出的排序输出中必须保持相同的顺序
。 -stable排序,5s可能在排序后的输出中以相反的顺序



这表明排序是正确的,但是它发生了变化。因此,在现实世界中,即使排序正确无误,我们也必须确保获得期望的结果!这也非常重要,请记住这一点。有关更多JavaScript示例,请查看Array.prototype.sort()-文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

评论


您大摇大摆,谢谢您给予这个难以置信的答案。我在SO上看到的最好的之一。干杯。

–加文
18-10-12在18:57

如果您只能提供一个怪异的方法,最后使用。很好的答案!

–mmm
19年1月27日在18:59



@momomo问题是,根据您对排序的期望,没有正确的方法。但是,您可以从我的答案中简单地使用这段代码:Object.keys(testObj).sort()。reduce((a,c)=>(a [c] = testObj [c],a),{}) 。

– Megajin
19年2月22日在7:25

排序的稳定性是否不适用于此问题:我们正在按对象键进行排序,并且键是唯一的。 (以您的卡片示例为例:即使包装不同,包装中也永远不会有两个5s。)

–达伦·库克(Darren Cook)
1月27日12:21

@DarrenCook好问题!您是对的,在一个对象中永远不会有相同的键。但是,稳定性不仅仅是密钥的唯一性。大多数情况下,将数组包含在排序对象中。那就是一切都会变得不稳定的时候。想象一下一个有5个玩家的纸牌游戏。每只手都由一个数组(保持单个手排序)表示,而纸牌则作为对象。如果您的卡片看起来像{5:'hearts'}或{5:'spades'},并且您开始对数组进行排序,则在拉米纸牌游戏中它可能会变得不稳定。不要说不同的语言。

– Megajin
1月28日下午16:05

#5 楼

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

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


评论


我们如何按键对嵌套对象进行排序?

–a2441918
19年5月9日在16:47

@ a2441918与使用sort()函数的方式相同。看看:developer.mozilla.org/de/docs/Web/JavaScript/Reference / ... Object.fromEntries(Object.entries({b:3,a:8,c:1})。sort((k,j )=> k-j))

–user2912903
19-10-21在9:56

对于TypeScript用户,此功能尚不可用,请参阅:github.com/microsoft/TypeScript/issues/30933

–乔丹
2月17日上午11:06

不错的单行代码,但是如何以不区分大小写的方式对键进行排序?

–TheMaxx
3月22日12:21

@theMaxx使用自定义函数进行排序,例如:```Object.fromEntries(Object.entries({b:3,a:8,c:1})。sort(([[key1,val1],[key2, val2])=> key1.toLowerCase()。localeCompare(key2.toLowerCase())))

–本
3月23日16:18

#6 楼

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




评论


这种疯狂的语法到底是什么? (o [k] = v,o)。为什么这甚至行得通,在哪里可以找到有关它的文档?它显然返回最右边的参数,但是为什么呢?

– ntaso
19年7月9日在9:37



@ntaso在这里

–詹姆斯
19年7月11日在20:51

短函数首先使o [k]等于v,然后返回o

–塔欣·图尔科兹(Tahsin Turkoz)
19年8月6日在23:34

#7 楼

这对我有用

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


评论


这实际上是眼前问题的正确答案。有关使用Underscore的简化版本,请参见:jsfiddle.net/wPjaQ/1

–radicand
13年4月26日在10:30



@radicand不,此答案不正确。它返回一个没有顺序的新对象。

– Paul
13年7月12日在21:50

@radicand实际上也没有。没有对象键上的顺序这样的东西,那么您怎么能说实际上给您的对象是排序的呢?它实际上只是为您提供了传入对象的浅表副本。

– Paul
13年7月15日在15:39

这是超级错误的。它可能暂时可以使用,但是会在不同的Web浏览器中中断或在同一浏览器中加载不同的页面。为了安全起见,浏览器可能会随机分配对象密钥,或者在您填充对象时,它将根据密钥将值放入不同的存储桶中,这将返回不同的顺序。如果这种方法奏效了,那对您来说就是幸运的。

– Yobert
2014年10月1日在6:06

它还不需要使用jQuery。

–RobG
2014年12月1日7:17

#8 楼

这是一个古老的问题,但是从Mathias Bynens的答案中得到的提示,我做了一个简短的版本来对当前对象进行排序,而没有太多的开销。

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


执行代码后,“无序”对象本身将按字母顺序对键进行排序。

#9 楼

使用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();


值得深思。

#10 楼

假设它在显示无序对象属性的VisualStudio调试器中很有用。
(function(s) {
    var t = {};

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

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


评论


太好了,谢谢

– Mugiwara
2014年1月1日于20:43

真好!谢谢您提出的这个简洁的解决方案。

– Con Antonakos
2015年11月5日在16:28

#11 楼

下划线版本:

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


如果您不信任浏览器来保持键的顺序,我强烈建议您使用成对的键值配对数组数组。

_.sortBy(_.pairs(c),function(o){return o[0]})


评论


更好:_.object(_。sortBy(_。pairs(无序),_.first))

– Afanasii Kurakin
19年4月24日在8:33



#12 楼

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

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


评论


也许添加一些代码解释会更好。

– aristotll
17年8月26日在16:57

获取对象的键,所以它是字符串数组,我对其进行sort(),由于它是字符串(键)数组,因此我将其缩小(使用js Array的reduce())。 acc最初是一个空对象{}(reducer的最后一个arg),而reducer(回调)在该空对象上分配源obj的值以及有序的键序列。

–user3286817
17年8月29日在5:32

#13 楼

也许更优雅一些:




  /**
     * 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.与ES6 +语法相同:

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


评论


没什么您仍然返回一个对象。您无法保证目标中的对象实际上将具有任何顺序。您需要返回一个数组。 ee

–mmm
19年1月27日在18:58

您在这里要做的唯一一件事就是以非最佳方式确保它是一个集合。

–mmm
19年1月27日在18:59

#14 楼

实际上,我很惊讶地给出了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));


评论


对我来说也是一样!我滚动浏览以找到对该问题的深入解决方案(在发布自己的答案之前,该答案与您的答案相同)。但是后来我看到了你的,并赞成了。 :)

– Venryx
10月24日5:34

#15 楼

递归排序,用于嵌套对象和数组

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


评论


我认为您需要在其中放置其他对象-Array.isArray(obj [key])和typeof obj [key] ==='object'可能都适用

– jononomo
18-4-26在6:44



当您具有基本元素数组时,函数会将基本元素(字符串/数字)转换为空对象。为了解决这个问题,我在函数的开头添加了以下权限:function sortObjectKeys(obj){:if(typeof obj!='object'){/ *这是一个原始值:数字/字符串(在数组中)* /返回obj; }。为了健壮起见,我还从一开始就添加了:if(obj == null || obj == undefined){return obj; }

–已通过
19年2月26日在14:16

var sortKeys =(无序)=> {函数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)否则a [k] = vl返回a;},{}):(isAr?obj.map(srt): obj); } console.log(JSON.stringify(srt(unordered),null,4))}

–阿赫里什·库马尔(Akhilesh Kumar)
8月26日12:33

上面可以帮助保存数组,在您的解决方案中,数组也将转换为类似数组的对象

–阿赫里什·库马尔(Akhilesh Kumar)
8月26日12:35

在某些情况下,此解决方案可以将数组转换为对象。 (例如,数组内的数组)

– Venryx
10月24日5:26

#16 楼

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


评论


如果您没有为了清晰起见而将其折断,那么这可能适合于单行代码,对于一圈循环的单线而言,这值得我们多加赞赏。很好地使用了散布运算符进行合并,我总是以相同的方式进行操作,但是先分配后返回,所以通过解决方案学到了一些东西:)

– Steve Goossens
6月15日21:23



#17 楼

如前所述,对象是无序的。

但是...

您可能会发现这个惯用法很有用:

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

var kv = [];

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

kv.sort()


然后您可以遍历kv并做您想做的任何事情。

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


评论


实际上,在ES6中,对象是有序的。

–马蒂亚斯·拜恩斯(Mathias Bynens)
2015年6月28日17:26



#18 楼

这是一个基于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;
};


如果lodash使用toObject()方法,它甚至会更加干净...

#19 楼

@sindresorhus有一个很棒的项目叫做sort-keys,它很棒。

您可以在这里查看其源代码:

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

或者您可以将其与npm一起使用:

$ npm install --save sort-keys


这也是他的自述文件中的代码示例

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}


#20 楼

只需使用lodash解压缩地图并再次按pair和zip的第一个值,它将返回已排序的键。

如果要让sortby值将对索引更改为1而不是0

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




评论


请使用编辑链接来说明此代码的工作原理,而不仅仅是给出代码,因为这样的解释更有可能对未来的读者有所帮助。另请参阅“如何回答”。资源

–杰德·福克斯(Jed Fox)
17年1月10日在23:40

#21 楼

在保留引用的同时递归地对键进行排序。

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


示例:

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}


评论


不错的摘要!删除o [e [0]]的目的是什么?那里?我们不能只分配吗?

– Bo阳
18-10-19在4:11

似乎只有对不存在的键的新分配将在末尾附加该键。如果删除操作被注释掉,则不会对键进行排序,至少不会在Chrome中排序。

–不列颠人
18-10-20在8:51

这就说得通了。谢谢!在任何情况下,这都是一个失败的原因,因为根据规范js对象键没有顺序。我们只是利用obj和log函数的隐含细节

– Bo阳
18-10-23在9:21

是的,当键的顺序很重要时,我使用Map:developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/…

–不列颠人
18-10-24在11:21

#22 楼

这是我进行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;
    }, {});
}


评论


注意:这不仅会排序键,还会排序数组项!

– Venryx
10月24日5:27

#23 楼

如果您有嵌套的对象或嵌套的数组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;
};


评论


作者没有说自己正在使用jQuery,也没有标注jQuery。如果您在纯JavaScript中添加解决方案,那就太好了。

– rusmus
2014-02-25 14:53

谢谢@Phani,这正是我所需要的

–谢泼德(Will Sheppard)
16 Mar 18 '16 at 14:47

#24 楼

解决方案:

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


说明:

许多JavaScript运行时都按照添加值的顺序将值存储在对象中。

要按对象的键对对象的属性进行排序,可以使用Object.keys函数,该函数将返回键的数组。然后可以通过Array.prototype.sort()方法对键数组进行排序,该方法对数组元素进行适当排序(无需将它们分配给新变量)。

一旦键排序后,您可以开始一个个地使用它们来访问旧对象的内容以填充新对象(现在已排序)。

下面是该过程的示例(您可以在目标浏览器中对其进行测试):




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





注意: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;
  };
}


#25 楼

我将一些Java枚举转移到javascript对象。

这些对象为我返回了正确的数组。如果对象键是混合类型(字符串,整数,字符),则存在问题。




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


#26 楼

纯JavaScript答案可对对象进行排序。我知道这是唯一可以处理负数的答案。此功能用于对数字对象进行排序。

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


输出将是一个对象,这些对象按这些数字排序,并且新键从0开始。

#27 楼

使用lodash的简单易懂的代码段。

仅在调用sortBy时才需要将键放在引号中。它不必在数据本身的引号中。

_.sortBy(myObj, "key")


此外,您要映射的第二个参数是错误的。它应该是一个函数,但是使用pluck更容易。

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


评论


_.sortBy(myObj,“ key”)将按属于集合项的键(即myObj.item.key)而不是myObj本身(myObj.item,其中“ item”为对象)对集合进行排序。

–matharden
6月25日11:29

#28 楼

只是为了简化并使其更加清晰,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]);
} 




#29 楼

不知道这是否能回答问题,但这就是我所需要的。

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


称呼为:

Maps.iterate.sorted({c:1, b:2, a:100}, function(k, v) { ... } ) 


#30 楼

一行:

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