Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/440.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用backbone.js按相反顺序排序字符串_Javascript_Sorting_Backbone.js_Underscore.js - Fatal编程技术网

Javascript 使用backbone.js按相反顺序排序字符串

Javascript 使用backbone.js按相反顺序排序字符串,javascript,sorting,backbone.js,underscore.js,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, titl

我正在尝试按相反的顺序对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对章节进行排序?

如果您使用的是非数值,则没有明显的方法进行反向排序。主干使用下划线中的
.sortBy()
.sortedIndex()
方法基于比较器对模型进行排序,这些方法自动按升序排序。最简单的方法是使用
chapters.pull('title').reverse()
,因为
pull
的结果将是一个数组。但是在某些收集方法上调用
reverse
,将反转就地收集模型,因此下次调用时,模型将按升序返回。您可以随时执行以下操作:

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

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

results.reverse();
这个概念可能需要改进,以考虑符号等,但本质上它将比较器字符串反转为“Z”变为“0”,“Y”变为“1”等,这将产生您所追求的反向排序。

您可以:

  • 获取字符串中每个字符的字符代码
  • 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"]

注意:如果您的比较字符串很长(如65KB或更大),您可能会遇到问题(请参阅下面Matt的评论)。为了避免这种情况,并加快比较速度,只需使用比较字符串的较短片段。(在上面的示例中,您可以选择
chapter.get(“title”).slice(0,100).split(“”)
)所需的切片长度取决于您的应用程序。

因为主干网仅使用.sortBy方法,只需在您自己的逻辑中代理即可:

collectionInQuestion.sortBy = function () {
  var models = _.sortBy(this.models, this.comparator);
  if (forSomeReason) {
    models.reverse();
  }
  return models;
};
…或将其添加到其他地方

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

只需在
章节前加上负号即可。获取

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

您可以使用比较器函数的两个版本,一个是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"

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

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。

示例来自文档:-在比较器中使用“title”而不是“page”。可能的重复不是重复,这个问题的不同之处在于需要排序字符串,而不是像另一个问题中建议的那样,用减号无法排序的数字。这里有一个解决方案,它将反转任何排序比较器的方向,不管它是什么类型:您的比较器函数现在可以是传递给sort()的函数,不再需要这种黑客行为。请看@Filip,我遇到了一个问题,
fromCharCode.apply
在使用很长的数组调用Safari时会锁定Safari。长度大于65536的数组将导致它完全失败并抛出RangeError。也许可以通过从比较字符串中提取第一个
n
字符的一部分,使这个比较器函数更安全(并且可能更有效)。这并不是在所有情况下都有效。对字符串排序时,1)“2010-2013”,2)“2011-2013”,3)“2006-2010”asc顺序为3 1 2,desc顺序应为2 1 3。但实际得到的是描述顺序的1 2 3。在执行此操作之前,应将字符串转换为相同的大小写。请注意,此方法并不总是正确的。例如,
foo
foobar
的顺序不会颠倒。这主要可以通过在字符串末尾添加
String.fromCharCode(0xffff)
来解决。这不适用于字符串,这篇文章就是关于字符串的。我创建了一个变体,它也适用于数字和字符串。可以在这里找到:制作一个不太具体的版本的想法很好。您可以使用此比较器使集合按相反顺序排序:
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();
    }

},