按值对 JSON 进行排序
Posted
技术标签:
【中文标题】按值对 JSON 进行排序【英文标题】:Sorting JSON by values 【发布时间】:2010-10-27 06:15:09 【问题描述】:我有一个非常简单的 JSON 对象,如下所示:
"people":[
"f_name":"john",
"l_name":"doe",
"sequence":"0",
"title":"president",
"url":"google.com",
"color":"333333"
,
"f_name":"michael",
"l_name":"goodyear",
"sequence":"0",
"title":"general manager",
"url":"google.com",
"color":"333333"
]
现在这是从我的服务器端代码返回的,我运行 jQuery.each
以形成必要的 html 并输出结果。
现在我正在做的是向包含我的排序信息的服务器发送 AJAX 调用......例如“标题 DESC”并重新运行 SQL 查询以返回新的结果集。但我想避免这种情况,并使用 jQuery 对生成的 JSON 进行排序,以防止往返服务器和多个数据库访问。
如何使用 jQuery 实现这一点?
【问题讨论】:
你可能想试试这个的变体:wrichards.com/blog/2009/02/jquery-sorting-elements 仅供参考...您可以使用 Internet 上有关 javascript 数组排序的任何教程,它会直接应用于您的场景,因为 JSON 只是一个 javascript 对象/数组。 JS 没有区分对象和数组,因为无论如何在 JS 中一切基本上都是对象。 :-) @Emin,请考虑更改接受的答案,因为我提供的答案现在收到的赞成票几乎是之前接受的答案的两倍。 @SeantheBean true.. 做到了.. Sort array of objects by string property value in JavaScript的可能重复 【参考方案1】:jQuery 对排序不是特别有帮助,但这是一个优雅而高效的解决方案。只需编写一个普通的 JS 函数,它接受属性名称和顺序(升序或降序)并使用简单的比较函数调用本机 sort() 方法:
var people = [
"f_name": "john",
"l_name": "doe",
"sequence": "0",
"title" : "president",
"url" : "google.com",
"color" : "333333",
// etc
];
function sortResults(prop, asc)
people.sort(function(a, b)
if (asc)
return (a[prop] > b[prop]) ? 1 : ((a[prop] < b[prop]) ? -1 : 0);
else
return (b[prop] > a[prop]) ? 1 : ((b[prop] < a[prop]) ? -1 : 0);
);
renderResults();
然后:
sortResults('l_name', true);
使用一个工作示例here。
【讨论】:
当我再输入几行数据时,这似乎对我不起作用。每次我尝试时,它的排序似乎都不同。这是小提琴:jsfiddle.net/Jsar8 任何帮助表示赞赏。 令人惊讶的是,Chrome(以及其他一些主要浏览器)不使用“稳定”(即一致?)排序算法。以下问题对浏览器的排序方法有一些很好的讨论:***.com/questions/1427608/…***.com/questions/234683/…***.com/questions/3026281/… 重要限制:核心排序功能在 FF 上工作,在 Chrome 24 上失败,在 android 默认浏览器上失败。 jsfiddle.net/VAKrE/377 这个函数本来就很优雅! @Hugolpz 准确地说,Chrome、Opera ***.com/questions/3026281 和我在互联网上能找到的最佳信息)。 FF 3+、Opera 10+、IE、Safari中使用的算法是稳定的。我之前评论中的相关 SO 问题更深入地介绍了 Array.sort() 实现。 @eaj 你指出 ECMAScript 标准是正确的——这是我的疏忽——我会相应地更新代码。但是,结果实际上是相同的,正如您在此处看到的那样:jsfiddle.net/Jsar8/1(基于 Jeff Borden 的问题示例)。只要有可能,请提供一个可行的例子来说明您的建议。【参考方案2】:演示:https://jsfiddle.net/kvxazhso/
成功传递相等的值(保持相同的顺序)。灵活:处理升序(123)或降序(321),适用于数字、字母和 unicode。适用于所有经过测试的设备(Chrome、Android 默认浏览器、FF)。
给定数据:
var people = [
'myKey': 'A', 'status': 0 ,
'myKey': 'B', 'status': 3 ,
'myKey': 'C', 'status': 3 ,
'myKey': 'D', 'status': 2 ,
'myKey': 'E', 'status': 7 ,
...
];
升序或倒序排序:
function sortJSON(arr, key, way)
return arr.sort(function(a, b)
var x = a[key]; var y = b[key];
if (way === '123') return ((x < y) ? -1 : ((x > y) ? 1 : 0));
if (way === '321') return ((x > y) ? -1 : ((x < y) ? 1 : 0));
);
people2 = sortJSON(people,'status', '321'); // 123 or 321
alert("2. After processing (0 to x if 123; x to 0 if 321): "+JSON.stringify(people2));
【讨论】:
【参考方案3】:jQuery.fn.sort = function()
return this.pushStack( [].sort.apply( this, arguments ), []);
;
function sortLastName(a,b)
if (a.l_name == b.l_name)
return 0;
return a.l_name> b.l_name ? 1 : -1;
;
function sortLastNameDesc(a,b)
return sortLastName(a,b) * -1;
;
var people= [
"f_name": "john",
"l_name": "doe",
"sequence": "0",
"title" : "president",
"url" : "google.com",
"color" : "333333",
,
"f_name": "michael",
"l_name": "goodyear",
"sequence": "0",
"title" : "general manager",
"url" : "google.com",
"color" : "333333",
]
sorted=$(people).sort(sortLastNameDesc);
【讨论】:
查看我对 Bill Richards 代码的改编。它根据姓氏按降序对 json 数组进行排序。排序回调可以通过在函数的构造函数中传递字段名称来概括。 你必须在 sortLastName 中用 l_name 替换 innerHTML 澄清一下,我的第一条评论,我的意思是这段代码可以进一步修改以支持通用排序。 如果 a.l_name 和 b.l_name 相等,sortLastName() 不应该返回 0 吗?可能是因为数据的原因,这种情况下是没有必要的,但是看了代码,我不禁想到了这个:blogs.msdn.com/oldnewthing/archive/2009/05/08/9595334.aspx ... “首先,你的第一个比较函数明显违反了做比较的要求功能:如果两个项目比较相等,它必须返回零。” 是的,你是对的。当两者相等时,它应该返回 0。正如我所说,这是对其他地方的代码的快速改编。目的只是为了展示这个概念,所以我看的不够仔细。【参考方案4】:如果您不介意使用外部库,Lodash 有很多很棒的实用程序
var people = [
"f_name":"john",
"l_name":"doe",
"sequence":"0",
"title":"president",
"url":"google.com",
"color":"333333"
,
"f_name":"michael",
"l_name":"goodyear",
"sequence":"0",
"title":"general manager",
"url":"google.com",
"color":"333333"
];
var sorted = _.sortBy(people, "l_name")
您还可以按多个属性进行排序。 Here's 一个在行动中展示它的笨蛋
【讨论】:
【参考方案5】:解决方案适用于不同类型和大小写。例如,如果没有 toLowerCase
语句,“Goodyear”将按升序排列在“doe”之前。运行我答案底部的代码 sn-p 以查看不同的行为。
JSON 数据:
var people = [
"f_name" : "john",
"l_name" : "doe", // lower case
"sequence": 0 // int
,
"f_name" : "michael",
"l_name" : "Goodyear", // upper case
"sequence" : 1 // int
];
JSON 排序函数:
function sortJson(element, prop, propType, asc)
switch (propType)
case "int":
element = element.sort(function (a, b)
if (asc)
return (parseInt(a[prop]) > parseInt(b[prop])) ? 1 : ((parseInt(a[prop]) < parseInt(b[prop])) ? -1 : 0);
else
return (parseInt(b[prop]) > parseInt(a[prop])) ? 1 : ((parseInt(b[prop]) < parseInt(a[prop])) ? -1 : 0);
);
break;
default:
element = element.sort(function (a, b)
if (asc)
return (a[prop].toLowerCase() > b[prop].toLowerCase()) ? 1 : ((a[prop].toLowerCase() < b[prop].toLowerCase()) ? -1 : 0);
else
return (b[prop].toLowerCase() > a[prop].toLowerCase()) ? 1 : ((b[prop].toLowerCase() < a[prop].toLowerCase()) ? -1 : 0);
);
用法:
sortJson(people , "l_name", "string", true);
sortJson(people , "sequence", "int", true);
var people = [
"f_name": "john",
"l_name": "doe",
"sequence": 0
,
"f_name": "michael",
"l_name": "Goodyear",
"sequence": 1
,
"f_name": "bill",
"l_name": "Johnson",
"sequence": 4
,
"f_name": "will",
"l_name": "malone",
"sequence": 2
,
"f_name": "tim",
"l_name": "Allen",
"sequence": 3
];
function sortJsonLcase(element, prop, asc)
element = element.sort(function(a, b)
if (asc)
return (a[prop] > b[prop]) ? 1 : ((a[prop] < b[prop]) ? -1 : 0);
else
return (b[prop] > a[prop]) ? 1 : ((b[prop] < a[prop]) ? -1 : 0);
);
function sortJson(element, prop, propType, asc)
switch (propType)
case "int":
element = element.sort(function(a, b)
if (asc)
return (parseInt(a[prop]) > parseInt(b[prop])) ? 1 : ((parseInt(a[prop]) < parseInt(b[prop])) ? -1 : 0);
else
return (parseInt(b[prop]) > parseInt(a[prop])) ? 1 : ((parseInt(b[prop]) < parseInt(a[prop])) ? -1 : 0);
);
break;
default:
element = element.sort(function(a, b)
if (asc)
return (a[prop].toLowerCase() > b[prop].toLowerCase()) ? 1 : ((a[prop].toLowerCase() < b[prop].toLowerCase()) ? -1 : 0);
else
return (b[prop].toLowerCase() > a[prop].toLowerCase()) ? 1 : ((b[prop].toLowerCase() < a[prop].toLowerCase()) ? -1 : 0);
);
function sortJsonString()
sortJson(people, 'l_name', 'string', $("#chkAscString").prop("checked"));
display();
function sortJsonInt()
sortJson(people, 'sequence', 'int', $("#chkAscInt").prop("checked"));
display();
function sortJsonUL()
sortJsonLcase(people, 'l_name', $('#chkAsc').prop('checked'));
display();
function display()
$("#data").empty();
$(people).each(function()
$("#data").append("<div class='people'>" + this.l_name + "</div><div class='people'>" + this.f_name + "</div><div class='people'>" + this.sequence + "</div><br />");
);
body
font-family: Arial;
.people
display: inline-block;
width: 100px;
border: 1px dotted black;
padding: 5px;
margin: 5px;
.buttons
border: 1px solid black;
padding: 5px;
margin: 5px;
float: left;
width: 20%;
ul
margin: 5px 0px;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="buttons" style="background-color: rgba(240, 255, 189, 1);">
Sort the JSON array <strong style="color: red;">with</strong> toLowerCase:
<ul>
<li>Type: string</li>
<li>Property: lastname</li>
</ul>
<button onclick="sortJsonString(); return false;">Sort JSON</button>
Asc Sort
<input id="chkAscString" type="checkbox" checked="checked" />
</div>
<div class="buttons" style="background-color: rgba(255, 214, 215, 1);">
Sort the JSON array <strong style="color: red;">without</strong> toLowerCase:
<ul>
<li>Type: string</li>
<li>Property: lastname</li>
</ul>
<button onclick="sortJsonUL(); return false;">Sort JSON</button>
Asc Sort
<input id="chkAsc" type="checkbox" checked="checked" />
</div>
<div class="buttons" style="background-color: rgba(240, 255, 189, 1);">
Sort the JSON array:
<ul>
<li>Type: int</li>
<li>Property: sequence</li>
</ul>
<button onclick="sortJsonInt(); return false;">Sort JSON</button>
Asc Sort
<input id="chkAscInt" type="checkbox" checked="checked" />
</div>
<br />
<br />
<div id="data" style="float: left; border: 1px solid black; width: 60%; margin: 5px;">Data</div>
【讨论】:
【参考方案6】:这是一个多级排序方法。我包含来自 Angular JS 模块的 sn-p,但是您可以通过限定排序键对象的范围来完成相同的事情,以便您的排序函数可以访问它们。你可以在Plunker看到完整的模块。
$scope.sortMyData = function (a, b)
var retVal = 0, key;
for (var i = 0; i < $scope.sortKeys.length; i++)
if (retVal !== 0)
break;
else
key = $scope.sortKeys[i];
if ('asc' === key.direction)
retVal = (a[key.field] < b[key.field]) ? -1 : (a[key.field] > b[key.field]) ? 1 : 0;
else
retVal = (a[key.field] < b[key.field]) ? 1 : (a[key.field] > b[key.field]) ? -1 : 0;
return retVal;
;
【讨论】:
以上是关于按值对 JSON 进行排序的主要内容,如果未能解决你的问题,请参考以下文章
node.js - 按值对 JSON 对象进行排序 [重复]