在Javascript中对JSON对象进行排序

21

我已经寻找了一段时间,想要对这个类似以下结构的JSON对象进行排序

{"results": [
  {
    "layerId": 5,
    "layerName": "Pharmaceutical Entities",
    "attributes": {
      "OBJECTID": "35",
      "FACILITYTYPE": "Pharmacy",
      "FACILITYSUBTYPE": "24 Hr Pharmacy",
      "COMMERCIALNAME_E": "SADD MAARAB PHARMACY",
      },
    "geometryType": "esriGeometryPoint",
   },
  {
    "layerId": 5,
    "layerName": "Pharmaceutical Entities",
    "attributes": {
      "OBJECTID": "1",
      "FACILITYTYPE": "Pharmacy",
      "FACILITYSUBTYPE": "24 Hr Pharmacy",
      "COMMERCIALNAME_E": "GAYATHY HOSPITAL  PHARMACY",

    },
    "geometryType": "esriGeometryPoint",
  },
     {
    "layerId": 5,
    "layerName": "Pharmaceutical Entities",
    "attributes": {
      "OBJECTID": "255",
      "FACILITYTYPE": "Pharmacy",
      "FACILITYSUBTYPE": "24 Hr Pharmacy",
      "COMMERCIALNAME_E": "AL DEWAN PHARMACY",
      },
    "geometryType": "esriGeometryPoint",
   }
]}

按照"COMMERCIALNAME_E"的值按字母顺序排序以获取

{"results": [
   {
    "layerId": 5,
    "layerName": "Pharmaceutical Entities",
    "attributes": {
      "OBJECTID": "255",
      "FACILITYTYPE": "Pharmacy",
      "FACILITYSUBTYPE": "24 Hr Pharmacy",
      "COMMERCIALNAME_E": "AL DEWAN PHARMACY",
      },
    "geometryType": "esriGeometryPoint",
   },
  {
    "layerId": 5,
    "layerName": "Pharmaceutical Entities",
    "attributes": {
      "OBJECTID": "1",
      "FACILITYTYPE": "Pharmacy",
      "FACILITYSUBTYPE": "24 Hr Pharmacy",
      "COMMERCIALNAME_E": "GAYATHY HOSPITAL  PHARMACY",
       },
    "geometryType": "esriGeometryPoint",
   },
   {
    "layerId": 5,
    "layerName": "Pharmaceutical Entities",
    "attributes": {
      "OBJECTID": "35",
      "FACILITYTYPE": "Pharmacy",
      "FACILITYSUBTYPE": "24 Hr Pharmacy",
      "COMMERCIALNAME_E": "SADD MAARAB PHARMACY",
      },
    "geometryType": "esriGeometryPoint",
   }
]}

我找不到任何可以实现这个功能的代码。有人能给我一些帮助吗?

6个回答

41
function sortJsonArrayByProperty(objArray, prop, direction){
    if (arguments.length<2) throw new Error("sortJsonArrayByProp requires 2 arguments");
    var direct = arguments.length>2 ? arguments[2] : 1; //Default to ascending

    if (objArray && objArray.constructor===Array){
        var propPath = (prop.constructor===Array) ? prop : prop.split(".");
        objArray.sort(function(a,b){
            for (var p in propPath){
                if (a[propPath[p]] && b[propPath[p]]){
                    a = a[propPath[p]];
                    b = b[propPath[p]];
                }
            }
            // convert numeric strings to integers
            a = a.match(/^\d+$/) ? +a : a;
            b = b.match(/^\d+$/) ? +b : b;
            return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) );
        });
    }
}

sortJsonArrayByProperty(results, 'attributes.OBJECTID');
sortJsonArrayByProperty(results, 'attributes.OBJECTID', -1);

更新:不要改变

function sortByProperty(objArray, prop, direction){
    if (arguments.length<2) throw new Error("ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION");
    if (!Array.isArray(objArray)) throw new Error("FIRST ARGUMENT NOT AN ARRAY");
    const clone = objArray.slice(0);
    const direct = arguments.length>2 ? arguments[2] : 1; //Default to ascending
    const propPath = (prop.constructor===Array) ? prop : prop.split(".");
    clone.sort(function(a,b){
        for (let p in propPath){
                if (a[propPath[p]] && b[propPath[p]]){
                    a = a[propPath[p]];
                    b = b[propPath[p]];
                }
        }
        // convert numeric strings to integers
        a = a.match(/^\d+$/) ? +a : a;
        b = b.match(/^\d+$/) ? +b : b;
        return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) );
    });
    return clone;
}

const resultsByObjectId = sortByProperty(results, 'attributes.OBJECTID');
const resultsByObjectIdDescending = sortByProperty(results, 'attributes.OBJECTID', -1);

是的,对于排序json没有“简单”的解决方案。但是确实有解决方案...你太棒了。 - Daniel Apps
感谢更新,为了可测试的代码,利用函数式编程的力量,我不再在我的函数中改变参数。 - PDA
值得注意的是,如果属性已经是整数,则a.match返回失败。 - user2051552
请注意,您从未使用方向参数。 - user1853517

11

首先提取JSON编码的数据:

var data = JSON.parse(yourJSONString);
var results = data['results'];

然后使用自定义(用户)函数进行排序:

results.sort(function(a,b){
    //return a.attributes.OBJECTID - b.attributes.OBJECTID;
    if(a.attributes.OBJECTID == b.attributes.OBJECTID)
        return 0;
    if(a.attributes.OBJECTID < b.attributes.OBJECTID)
        return -1;
    if(a.attributes.OBJECTID > b.attributes.OBJECTID)
        return 1;
});

我假设您想按OBJECTID排序,但您可以更改为按任何内容进行排序。


为什么要使用eval,而不是JSON.parse呢? - customcommander
@customcommander 很可能是因为这个答案是10年前的,当时JSON.parse在浏览器上的支持并不完整。如果您认为某些答案已经过时,请随意编辑。 - Alin Purcaru

5

你可以通过向Array.Sort()函数提供一个自定义比较函数的参数来对有序数组中的任何内容进行排序。

var myObject = /* json object from string */ ;

myObject.results.sort(function (a, b) {

    // a and b will be two instances of your object from your list

    // possible return values
    var a1st = -1; // negative value means left item should appear first
    var b1st =  1; // positive value means right item should appear first
    var equal = 0; // zero means objects are equal

    // compare your object's property values and determine their order
    if (b.attributes.COMMERCIALNAME_E < a.attributes.COMMERCIALNAME_E) {
        return b1st;
    }
    else if (a.attributes.COMMERCIALNAME_E < b.attributes.COMMERCIALNAME_E) {
        return a1st;
    }
    else {
        return equal;
    }
});

4

您可以通过 array.sort() 轻松完成此操作。

[
    { name: "Robin Van Persie", age: 28 },
    { name: "Theo Walcott", age: 22 },
    { name: "Bacary Sagna", age: 26  }
].sort(function(obj1, obj2) {
    // Ascending: first age less than the previous
    return obj1.age - obj2.age;
});
// Returns:  
// [
//    { name: "Theo Walcott", age: 22 },
//    { name: "Bacary Sagna", age: 26  },
//    { name: "Robin Van Persie", age: 28 }
// ]

以下示例源自此处,您可以从此处了解更多相关信息。


2

你不能对JSON字符串进行排序。JSON是用于数据传输的对象表示法,即一个字符串。你需要将其评估为对象字面量(例如使用eval),并在重新序列化之前进行任何想要的更改。


-3

从字符串中提取JSON

var data = eval(given_JSON_string);
var results = data['results'];

通过将自定义函数传递给排序方法进行排序

results.sort(customfunction);

自定义函数可以被定义为

function customfunction(a, b) {

return a.attributes.COMMERCIALNAME_E < b.attributes.COMMERCIALNAME_E ? 1 : -1;

}


为什么使用eval当你可以用JSON.parse呢? - customcommander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接