【问题标题】:Sorting JSON by values按值对 JSON 进行排序
【发布时间】: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.. 做到了..

标签: jquery json


【解决方案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(以及其他一些主要浏览器)不使用“稳定”(即一致?)排序算法。以下问题对浏览器的排序方法有一些很好的讨论:stackoverflow.com/questions/1427608/…stackoverflow.com/questions/234683/…stackoverflow.com/questions/3026281/…
  • 重要限制:核心排序功能在 FF 上工作,在 Chrome 24 上失败,在 Android 默认浏览器上失败。 jsfiddle.net/VAKrE/377 这个函数本来就很优雅!
  • @Hugolpz 准确地说,Chrome、Opera stackoverflow.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;
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-09-16
          • 2016-06-05
          • 2016-09-21
          • 2014-05-12
          • 2018-07-05
          • 2018-12-22
          • 2012-11-06
          • 1970-01-01
          相关资源
          最近更新 更多