如何按嵌套值对 JSON 对象进行排序?

Posted

技术标签:

【中文标题】如何按嵌套值对 JSON 对象进行排序?【英文标题】:How do I sort a JSON object by a nested value? 【发布时间】:2012-11-25 08:36:30 【问题描述】:

我有一个 ajax 调用,它返回一个非常复杂的 JSON 对象,我很难对其进行排序。

我的电话:

$.post('/reports-ajax',arguments, function(data) 

回应:


"10001":
    "unitname":"Fort Worth",
    "discounts":"12-02-2012":"34.810000","12-03-2012":"20.810000","12-04-2012":"27.040000",
    "gross":"12-02-2012":"56.730000","12-03-2012":"19.350000","12-04-2012":"66.390000",
    "net":"12-02-2012":"61.920000","12-03-2012":"98.540000","12-04-2012":"39.350000",
    "discounts_total":82.66,
    "gross_total":82.47,
    "net_total":99.81,
    "number":10001
    ,
"10002":
    "unitname":"Dallast",
    "discounts":"12-02-2012":"12.600000","12-03-2012":"25.780000","12-04-2012":"47.780000","12-05-2012":"45.210000",
    "gross":"12-02-2012":"29.370000","12-03-2012":"91.110000","12-04-2012":"60.890000","12-05-2012":"51.870000",
    "net":"12-02-2012":"16.770000","12-03-2012":"65.330000","12-04-2012":"13.110000","12-05-2012":"06.660000",
    "discounts_total":131.37,
    "gross_total":33.24,
    "net_total":101.87,
    "number":10002
    ,
"32402":
    "unitname":"Austin",
    "discounts":"12-05-2012":"52.890000","12-02-2012":"22.430000","12-03-2012":"58.420000","12-04-2012":"53.130000",
    "gross":"12-05-2012":"25.020000","12-02-2012":"2836.010000","12-03-2012":"54.740000","12-04-2012":"45.330000",
    "net":"12-04-2012":"92.200000","12-05-2012":"72.130000","12-02-2012":"13.580000","12-03-2012":"96.320000",
    "discounts_total":186.87,
    "gross_total":161.1,
    "net_total":174.23,
    "number":32402
    

我用标准的每次调用检查函数,并用 highcharts 做一些很棒的事情,但现在我试图通过 net_total 调用对响应进行排序,但我无法弄清楚。

我尝试了.sort(),但它错误地指出它不是一个函数。我已经阅读了一段时间,但我想我没有找到正确的结果。这看起来很有希望:Sorting an array of javascript objects 但它失败了,.sort is not a function。似乎大多数 .sort 都在 [] 数组上,而不是完整的对象..

任何帮助将不胜感激。

【问题讨论】:

这不是一个数组,它是一个对象。它具有名为 10001、10002 和 32402 的属性,这些属性本身不可排序。 Sorting a JavaScript object的可能重复 【参考方案1】:

你所拥有的不是数组,也没有顺序,所以你必须将它转换成数组,这样你才能给它排序。

含糊地说:

var array = [];
$.each(data, function(key, value) 
    array.push(value);
);
array.sort(function(a, b) 
    return a.net_total - b.net_total;
);

Live Example | Source

正如 GolezTroi 在 cmets 中指出的那样,通常上面会丢失每个条目存储在 data 下的密钥,因此您可以将其添加回上面的第一个 $.each 循环中,但在这种情况下条目上已经有密钥(如number),所以不需要。

或者你可以用$.map替换第一个$.each

var array = $.map(data, function(entry) 
    return entry;
);
// ...and then sort etc.

...随你喜欢。

【讨论】:

使用此方法会丢失密钥,但它的值仍可在数组中每个对象的属性number 中使用。 @GolezTrol:谢谢,我会添加注释。【参考方案2】:

对对象进行排序没有意义,因为对象键没有位置值。例如,这个:

 a:1, b:2 

还有这个:

 b:2, a:1 

是完全相同的对象。它们不仅相似,而且相同。

javascript 本身并没有给对象键任何位置值。有些人可能错误地认为:

for (var key in obj) 

以特定顺序遍历对象键。但这是错误的。您应该始终假设for .. in 循环始终以随机顺序处理对象键。

显然,如果您要编写 Web 浏览器,则不会实现随机数生成器来解析 for .. in 循环。因此,大多数网络浏览器对for .. in 循环处理对象键的方式意外稳定性。

通过玩弄浏览器来学习 javascript 的开发人员可能会发现,他们的浏览器会按字母顺序迭代对象,或者将键添加到对象的顺序。但这完全是偶然的,不能依赖。浏览器供应商将来可能会在不违反任何向后兼容性的情况下更改此行为(除了那些认为对象具有排序顺序的人编写的错误脚本)。更不用说不同的浏览器有不同的 javascript 实现,因此不一定有相同的对象内部键顺序。

以上都是题外话。 “键排序顺序”在 javascript 中没有任何意义,观察到的任何行为都只是实现细节。简而言之,javascript对象没有键顺序,只是假设它是随机的。


解决方案

现在,您真正想做的是对对象进行排序(您不能,这没有意义)。您真正想做的是按特定顺序处理对象属性。解决方案是简单地创建对象键的数组(具有排序顺序),然​​后使用该数组处理对象:

// First create the array of keys/net_total so that we can sort it:
var sort_array = [];
for (var key in Response) 
    sort_array.push(key:key,net_total:Response[key].net_total);


// Now sort it:
sort_array.sort(function(x,y)return x.net_total - y.net_total);

// Now process that object with it:
for (var i=0;i<sort_array.length;i++) 
    var item = Response[sort_array[i].key];

    // now do stuff with each item

【讨论】:

我喜欢 T.J 的回应,但这保持了重要的关键。

以上是关于如何按嵌套值对 JSON 对象进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

C#:按值对 json 对象进行排序

按值对 JSON 进行排序 [重复]

如何按对象中的值对数组进行排序

Android-java-如何按对象内的某个值对对象列表进行排序

如何对嵌套的ObjectData Flutter进行排序

根据嵌套键值对对象数组进行排序的最快方法