【问题标题】:Javascript - sorting JSON object by a nested valueJavascript - 按嵌套值对 JSON 对象进行排序
【发布时间】:2016-07-09 16:45:33
【问题描述】:

总结:有一个多级的父子评论系统。即

示例:

comment 1
    comment 1-1
        comment 1-1-1
    comment 1-2
        comment 1-2-1
             comment 1-2-2

这里,comment 1 是父级,comment 1-1comment 1-2 都是 comment 1 的子级 等等..

要求:

我们想基于property value.i.e.实现整个对象的sortingtimestamp(最新评论或回复会在最上面)。

JSON 对象:

{
  "CommentText": "",
  "CommentCreateStamp": "2016-03-22",
  "Comments": [{
    "CommentText": "comment 1",
    "CommentCreateStamp": "2016-03-09",
    "Comments": [{
      "CommentText": "comment 1-1",
      "CommentCreateStamp": "2016-03-15",
      "Comments": [{
        "CommentText": "comment 1-1-1",
        "CommentCreateStamp": "2016-03-21",
        "Comments": null
      }]
    }]
  }],
  "Comments": [{
    "CommentText": "comment 2",
    "CommentCreateStamp": "2016-03-12",
    "Comments": [{
      "CommentText": "comment 2-1",
      "CommentCreateStamp": "2016-03-10",
      "Comments": [{
        "CommentText": "comment 2-1-1",
        "CommentCreateStamp": "2016-03-14",
        "Comments": null
      }]
    }]
  }]
}

我试过了:

JSfiddle:https://jsfiddle.net/asceeevb/

我看到很多关于 * 的问题,但没有按要求工作。

任何直接的帮助都将是非常可观的。谢谢

【问题讨论】:

  • 所以你想要一个平面列表?
  • 如果结构应该保留,您只能在同一级别上排序。
  • @georg,不是一个平面列表。我希望根据CommentCreateStamp 属性以排序方式对数据进行排序。最新的 cmets 应该位于顶部,并且与子层次结构相同。我更新了 JSON 对象。请立即检查。
  • @NinaScholz,没有办法对分层结构进行排序?
  • 试试这个链接希望它对你有帮助。 *.com/questions/13758467/…

标签: javascript jquery json sorting


【解决方案1】:

我不完全确定您在问什么,但您的代码似乎有一些问题:

  • 您重新定义了对象的comments 属性,也许您想要一个数组?
  • 您的排序函数应该根据元素的比较返回一个值,而不是输出它。有关日期比较,请参阅 this SO question

更新:您很接近,您缺少的是对嵌套 cmets 的 sorting 的调用。 这是一个递归调用sorting的sn-p:

var people = {
  "CommentText": "",
  "CommentCreateStamp": "",
  "Comments": [{
    "CommentText": "c1",
    "CommentCreateStamp": "2016-03-23 06:05:36",
    "Comments": [{
      "CommentText": "c2",
      "CommentCreateStamp": "2016-03-23 06:05:59",
    }],
  }, {
    "CommentText": "a1",
    "CommentCreateStamp": "2017-03-23 06:05:45",
    "Comments": [{
      "CommentText": "a2",
      "CommentCreateStamp": "2016-03-23 06:06:05",
    }, {
      "CommentText": "a3",
      "CommentCreateStamp": "2016-03-23 06:06:16",
    }, {
      "CommentText": "a4",
      "CommentCreateStamp": "2016-03-23 06:06:23",
    }],
  }],
};



function sorting(js_object, key_to_sort_by) {

  function sortByKey(a, b) {
    var x = a[key_to_sort_by];
    var y = b[key_to_sort_by];
    return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  };

  js_object.sort(sortByKey);

};

function sortComments(comments) {
  
  sorting(comments, 'CommentCreateStamp');
  for (var i = 0; i < comments.length; i++)
    if (comments[i].hasOwnProperty('Comments'))
      sortComments(comments[i].Comments);

};

sortComments(people.Comments);
console.log(people.Comments);

【讨论】:

    【解决方案2】:

    您可以创建一个平面数组来保留引用并按CommentCreateStamp 对其进行排序。

    function getFlat(o) {
        this.push(o);
        Array.isArray(o.Comments) && o.Comments.forEach(getFlat.bind(this));
    }
    
    var object = { "CommentText": "", "CommentCreateStamp": "2016-03-22", "Comments": [{ "CommentText": "comment 1", "CommentCreateStamp": "2016-03-18", "Comments": [{ "CommentText": "comment 1-1", "CommentCreateStamp": "2016-03-15", "Comments": [{ "CommentText": "comment 1-1-1", "CommentCreateStamp": "2016-03-21", "Comments": null }] }] }] },
        flat = [];
    
    getFlat.bind(flat)(object);
    flat.sort(function (a, b) {
        return a.CommentCreateStamp.localeCompare(b.CommentCreateStamp);
    });
    document.write('<pre>' + JSON.stringify(flat, 0, 4) + '</pre>');

    【讨论】:

    • 感谢您的回答,但我希望排序对象不是相同格式的平面数组。
    【解决方案3】:

    稍微细化@changed 的​​答案——我发现以下方法效果很好:

      export function sortObj(jsObj, sortKey,flgReverse) {
        sortKey = sortKey.split(".");
        let sk = '';
        Object.keys(sortKey).forEach(function(key,idx){
        sk += '[\'' + sortKey[key] + '\']';
        });
        function sortByKey(a, b) {
          var x = eval("a" + sk);
          var y = eval("b" + sk);
          if(flgReverse) return  ((x < y) ? -1 : ((x > y) ? 1 : 0));
          else return ((x < y) ? 1 : ((x > y) ? -1 : 0));
        };
        return jsObj.sort(sortByKey);
      }; 
    

    【讨论】: