【问题标题】:Sorting backbone collections with multiple attributes对具有多个属性的主干集合进行排序
【发布时间】:2011-11-29 11:51:55
【问题描述】:

我正在尝试按用户可选择的创建日期或优先级对模型集合进行排序。

可以按降序或升序选择优先级,但模型会按创建日期以降序进一步排序。

创建日期也可以按降序或升序选择,无需进一步的子排序。

下面是我目前的代码:

comparator: function(task) {
  var sorter = task.get(root.sortAttr);
  var subSorter = String.fromCharCode.apply(String,
    _.map(task.get("created_at").split(""), function (c) {
      return 0xffff - c.charCodeAt();
    })
  );

  if(!root.sortAscending) {
    console.log("desc");
    return -sorter + ", " + subSorter;
  }
  else {
    console.log("asc");
    return sorter + ", " + subSorter;
  }
}

此代码适用于创建日期的升序和降序,但只会按降序显示优先级。谁能告诉我为什么会这样以及我能做些什么来解决这个问题?

【问题讨论】:

    标签: javascript backbone.js


    【解决方案1】:

    好的,假设您的模型中有一个属性priority

    简单的解决方法是:

    sortOrder: 'asc',
    comparator: function (item) {
      var timestamp = Date.parse(item.get('created_at')) * 1000;
      timestamp += item.get('priority');
    
      if (this.sortOrder === 'asc') {
        return timestamp;
      }
    
      return -timestamp;
    }
    

    更复杂的解决方案:

    sortBy: {'created_at': 'asc', 'priority': 'desc'},
    comparator: function (item) {
      var result = 0;
      for (var field in this.sortBy) {
          if (field === 'created_at') {
              result += (this.sortBy[field] === 'asc')
                     ? Date.parse(item.get('created_at')) * 1000
                     : -Date.parse(item.get('created_at')) * 1000;
          }
    
          if (field === 'priority') {
              result += (this.sortBy[field] === 'asc')
                     ? item.get(field)) * 1000
                     : -item.get(field)) * 1000;
          }
      }
    
      return result;
    }
    

    您可以扩展 sortBy 以使用其他字段,只需将其解析为 int。注意你自己,当数字变为 > Number.MAX_VALUE 或 Number.MIN_VALUE 时会失败。

    您可以为您的字段实现toInt() 方法,并在对象循环内不使用 if 的情况下使用所有方法。

    result += (this.sortBy[field] === 'asc')
            ? item.get(field).toInt() * 1000
            : -item.get(field).toInt() * 1000;
    

    【讨论】:

    • 这很有帮助。我仍然没有设法让它工作,因为这总是对同一方向的优先级和时间戳进行排序,而我需要先按升序对优先级进行排序,然后在每个优先级组中按降序对时间戳进行子排序。
    【解决方案2】:

    我最终使用了一种纯粹基于字符串的方法,它产生了我所追求的结果,并且在能够支持基于字符串的排序属性方面提供了更大的灵活性。

    this.tasks.comparator = function(task) {
      var priority = (task.get("priority_id")).toString();
      var timestamp = task.get("created_at");
    
      if (!sortAscending) {
        if (sortAttribute == "created_at") return negateString(timestamp);
        if (sortAttribute == "priority_id") return negateString(negateString(priority) + "-" + negateString(timestamp));
      }
      else {
        if (sortAttribute == "created_at") return timestamp;
        if (sortAttribute == "priority_id") return negateString(priority) + "-" + timestamp;
      }
    }
    
    this.tasks.sort();
    

    其中否定字符串函数与找到here的函数相同,并在下面复制如下:

    var negateString = function(s) {
      s = s.toLowerCase();
      s = s.split("");
      s = _.map(s, function(letter) { 
        return String.fromCharCode(-(letter.charCodeAt(0)));
      });
    
      return s.join("");
    };
    

    【讨论】:

      【解决方案3】:

      backbone 现在有两个可以比较的模型,只需将第二个参数添加到比较器函数中。不知道为什么文档没有更新。

      comparator: function (model, model2) {
        return (model1.get('some_attribute') > model2.get('some_attribute')) ? -1 : 1;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-30
        • 2022-11-23
        • 2012-12-25
        • 1970-01-01
        相关资源
        最近更新 更多