使用多个属性对主干集合进行排序

时间:2011-11-29 11:51:56

标签: javascript backbone.js

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

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

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

以下是我目前的代码:

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;
  }
}

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

3 个答案:

答案 0 :(得分:2)

好的,我们假设你的模型中有一个属性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而不使用if。

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

答案 1 :(得分:1)

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

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("");
};

答案 2 :(得分:1)

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

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