使用backbone.js 对字符串进行逆序排序

发布于 2024-11-01 07:17:37 字数 541 浏览 3 评论 0原文

我正在尝试以相反的顺序对 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 -> 排序?一个?

I'm trying to sort a Backbone.js collection in reverse order. There are previous replies on how to do this with integers, but none with strings.

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'));

The above code sorts the chapters from A -> Z, but how do I write a comparator that sorts it from Z -> A?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

笑着哭最痛 2024-11-08 07:17:37

您可以:

  • 获取字符串中每个字符的字符代码,
  • 0xffff 中减去每个值(string.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("")。)您需要的切片长度取决于您的申请。

You could:

  • grab the char code for each character in the string,
  • subtract each value from 0xffff (the maximum return value of string.charCodeAt),
  • use String.fromCharCode to turn that back into string of "negated" characters

and that will be your sorting key.

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

And voila:

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

Note: if your comparison strings are long (as in 65 kb or more), you may run into trouble (see Matt's comment below). To avoid this, and speed up comparisons a bit, just use a shorter slice of your comparison string. (In the above example, you could go for chapter.get("title").slice(0, 100).split("") instead.) How long a slice you need will depend on your application.

梦屿孤独相伴 2024-11-08 07:17:37

您可以使用两个版本的比较器函数,一种是 sortBy 版本 - 示例中所示,它采用一个参数;另一种是 sort - 您可以返回一个更标准的排序函数,文档说:

“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"

There are two versions of the comparator function that you can use, either the sortBy version - which was shown in the example, which takes one parameter, or sort - which you can return a more standard sort function, which the documentation says:

"sortBy" comparator functions take a model and return a numeric or string value by which the model should be ordered relative to others. "sort" comparator functions take two models, and return -1 if the first model should come before the second, 0 if they are of the same rank and 1 if the first model should come after.

So in this case, we can write a different comparator function:

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'));

So you should get as a response:

"The Middle", "The End", "The Beginning"
怀中猫帐中妖 2024-11-08 07:17:37

如果您正在处理非数字值,则没有明显的方法可以进行反向排序。 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 集合中的模型数组,因为它将在内存中创建一个全新的结果数组,但保留对原始模型的引用,因此调用诸如 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”等方式反转比较器字符串,这应该会产生您想要的反向排序。

If you're working with non-numerical values, there is no obvious way to do a reverse sort. Backbone makes use of the _.sortBy() and _.sortedIndex() methods from Underscore to order the models based on the comparator, and these methods automatically sort in ascending order. The naive way to do this would be to use chapters.pluck('title').reverse(), as the result of pluck will be an array. But calling reverse on some Collection methods will reverse the Collection models in place, so next time you call it, the models will be back in ascending order. You could always do something like:

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

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

results.reverse();

This would not affect the models array in your Backbone collection, as it would create a completely new results array in memory, but retain references to the original models, so calling things like save would still update the Collection state.

But that's not very elegant, and creates a lot of extra coding throughout your project any time you want to reverse the results. I think we can do better.

In order to make this work, you'll need to perform a bit of unwieldy JavaScript ninjary in your comparator method to make this work - note this is untested:

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

This concept probably needs improving to take into account symbols, etc., but essentially it inverts the comparator string in such a way that "Z" becomes "0", "Y" becomes "1", etc., which should produce the reverse sort you're after.

陈独秀 2024-11-08 07:17:37

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

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

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

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

As Backbone merely uses the .sortBy method, simply proxy in your own logic:

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

..or add it somewhere else..

TweakedCollection = Backbone.Collection.extend({ sortBy: [...] })
撑一把青伞 2024-11-08 07:17:37

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

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

},

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

I just solved a similar problem with table sorting and I wanted to share the code since I didn't find much help in these answers:

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

},

in this case I simply set comparator to string instead of a function; the string has to be the name of the property you want to sort by.
Then I just call reverse on the models if the order has to be inverse.

昔梦 2024-11-08 07:17:37

只需在chapter.get前添加减号即可

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

Just add minus before chapter.get

chapters.comparator = function(chapter) {
    return -chapter.get("title");
};      
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文