使用backbone.js以相反的顺序对字符串进行排序

时间:2011-04-12 14:25:22

标签: javascript sorting backbone.js underscore.js

我正在尝试以相反的顺序对Backbone.js集合进行排序。以前有关于如何使用整数执行此操作的回复,但没有带有字符串的回复。

var Chapter  = Backbone.Model;
var chapters = new Backbone.Collection;

chapters.comparator = function(chapter) {
  return chapter.get("title");
};

chapters.add(new Chapter({page: 9, title: "The End"}));
chapters.add(new Chapter({page: 5, title: "The Middle"}));
chapters.add(new Chapter({page: 1, title: "The Beginning"}));

alert(chapters.pluck('title'));

上面的代码对A - >中的章节进行了分类。 Z ,但是如何编写一个比较器来对其进行排序来自Z - > A

6 个答案:

答案 0 :(得分:45)

你可以:

  • 获取字符串中每个字符的字符代码,
  • 0xffffstring.charCodeAt的最大返回值)中减去每个值,
  • 使用String.fromCharCode将其转换回“否定”字符串

这将是你的排序键。

chapters.comparator = function(chapter) {
    return String.fromCharCode.apply(String,
        _.map(chapter.get("title").split(""), function (c) {
            return 0xffff - c.charCodeAt();
        })
    );
}

瞧:

> console.log(chapters.pluck('title'));
["The Middle", "The End", "The Beginning"]

注意:如果您的比较字符串很长(如65 kb或更多),您可能会遇到麻烦(请参阅下面的Matt评论)。为了避免这种情况,并加快比较速度,只需使用比较字符串的较短切片。 (在上面的示例中,您可以改为使用chapter.get("title").slice(0, 100).split("")。)您需要多长时间取决于您的应用程序。

答案 1 :(得分:20)

您可以使用比较器功能的两个版本, sortBy 版本 - 示例中显示了一个参数,或者排序 - 你可以返回一个更标准的排序函数,documentation说:

  

“sortBy”比较器函数接受一个模型并返回一个数值或字符串值,通过该值可以相对于其他模型对模型进行排序。 “sort”比较器函数有两个模型,如果第一个模型应该在第二个模型之前,则返回-1,如果它们具有相同的等级,则返回0,如果第一个模型应该在之后,则返回1。

所以在这种情况下,我们可以写一个不同的比较器函数:

var Chapter  = Backbone.Model;
var chapters = new Backbone.Collection;

chapters.comparator = function(chapterA, chapterB) {
  if (chapterA.get('title') > chapterB.get('title')) return -1; // before
  if (chapterB.get('title') > chapterA.get('title')) return 1; // after
  return 0; // equal
};

chapters.add(new Chapter({page: 9, title: "The End"}));
chapters.add(new Chapter({page: 5, title: "The Middle"}));
chapters.add(new Chapter({page: 1, title: "The Beginning"}));

alert(chapters.pluck('title'));

所以你应该作为回应:

"The Middle", "The End", "The Beginning"

答案 2 :(得分:12)

如果您正在处理非数值,则没有明显的方法可以进行反向排序。 Backbone使用Underscore中的_.sortBy()_.sortedIndex()方法根据比较器对模型进行排序,这些方法会自动按升序排序。这样做的天真方法是使用chapters.pluck('title').reverse(),因为pluck的结果将是一个数组。但是在某些Collection方法上调用reverse会反转Collection模型,所以下次调用它时,模型将按升序返回。你总是可以这样做:

var results = [],
    titles  = chapters.pluck('title');

for(var i=0, len=titles.length; i<len; i++) {
  results.push(titles[i]);
}

results.reverse();

这不会影响Backbone集合中的models数组,因为它会在内存中创建一个全新的结果数组,但保留对原始模型的引用,因此调用save之类的东西仍然会更新Collection状态

但这不是很优雅,并且只要您想要反转结果,就会在整个项目中创建大量额外的编码。我想我们可以做得更好。

为了完成这项工作,你需要在比较器方法中执行一些笨拙的JavaScript ninjary才能使其工作 - 注意这是未经测试的:

chapters.comparator = function(chapter) {
  var alphabet = '0123456789abcdefghijklmnopqrstuvwxyz',
      title = chapter.get('title').toLowerCase(),
      inverse_title = '',
      index;

  for(var i=0, len=title.length; i<len; i++) {
    index = alphabet.indexOf(title.charAt(i));

    if(index === -1) {
      inverse_title += title.charAt(i);
      continue;
    }

    inverse_title += alphabet.charAt(alphabet.length - index - 1);
  }

  return inverse_title;
};

这个概念可能需要改进以考虑符号等,但实质上它以“Z”变为“0”,“Y”变为“1”等方式反转比较器串,这应该是产生你想要的反向排序。

答案 3 :(得分:12)

由于Backbone仅使用.sortBy方法,只需在您自己的逻辑中进行代理:

collectionInQuestion.sortBy = function () {
  var models = _.sortBy(this.models, this.comparator);
  if (forSomeReason) {
    models.reverse();
  }
  return models;
};

..或将其添加到其他地方..

TweakedCollection = Backbone.Collection.extend({ sortBy: [...] })

答案 4 :(得分:0)

我刚刚用表格排序解决了类似的问题,我想分享代码,因为我在这些答案中没有找到太多帮助:

events: {

    'click th.sortable': function(e) {
        var $this = $(e.target),
            order = $this.hasClass('asc') ? 'desc' : 'asc',
            field = $this.data('field'); /* this is a string */

        $this.siblings().addBack().removeClass('asc desc');
        $this.addClass( order );

        this.bodyView.collection.comparator = field;
        this.bodyView.collection.sort();
        if ( order === 'desc' ) this.bodyView.collection.models.reverse();

        this.bodyView.render();
    }

},

在这种情况下,我只是将比较器设置为字符串而不是函数;字符串必须是要排序的属性的名称。 然后我只是在模型上调用reverse,如果顺序必须是反向的。

答案 5 :(得分:-4)

只需在chapter.get

之前添加减号
chapters.comparator = function(chapter) {
    return -chapter.get("title");
};