以与backbone.js相反的顺序sortingstring
我正在尝试按相反顺序对Backbone.js集合进行sorting。 以前有关于如何用整数做这个回答,但没有用string。
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中的章节sorting,但是如何编写一个从Z – > Asorting的比较器呢?
有两种版本的比较函数,你可以使用sortBy版本 – 在示例中显示,它带有一个参数,或者sorting – 你可以返回一个更标准的sorting函数, 文档说:
“sortBy”比较函数采用一个模型并返回一个数字或string值,通过该值可以将模型相对于其他模型sorting。 “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"
你可以:
- 获取string中每个字符的char代码,
- 从
0xffff
(string.charCodeAt
的最大返回值)中减去每个值, - 使用
String.fromCharCode
将其转换回“否定”string
那将是你的sorting键。
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"]
注意:如果比较string很长(如65 kb或更多),则可能会遇到麻烦(请参阅下面的Matt评论)。 为了避免这种情况,并加快比较,只需使用较短的比较string。 (在上面的例子中,你可以使用chapter.get("title").slice(0, 100).split("")
来代替。)你需要多长时间取决于你的应用程序。
如果您使用的是非数字值,则没有明显的方法来进行反向sorting。 主干使用来自_.sortBy()
和_.sortedIndex()
方法来对基于比较器的模型进行sorting,并且这些方法自动按升序sorting。 天真的做法是使用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数组,因为它会在内存中创build一个全新的结果数组,但保留对原始模型的引用,所以调用诸如save
东西仍然会更新Collection状态。
但是,这不是很优雅,并且在任何时候想要反转结果都会在整个项目中创build大量额外的代码。 我想我们可以做得更好。
为了使这个工作,你需要在你的比较器方法中执行一些笨拙的JavaScript忍者来做这个工作 – 注意这是未经testing的:
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”等,这将产生相反的sorting你后。
由于Backbone仅使用.sortBy方法,只需在您自己的逻辑中进行代理:
collectionInQuestion.sortBy = function () { var models = _.sortBy(this.models, this.comparator); if (forSomeReason) { models.reverse(); } return models; };
..或将其添加到其他地方..
TweakedCollection = Backbone.Collection.extend({ sortBy: [...] })
我刚刚解决了表格sorting类似的问题,我想分享代码,因为我没有find这些答案很多的帮助:
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(); } },
在这种情况下,我只是将比较器设置为string而不是函数; 该string必须是您想要sorting的属性的名称。 然后,如果顺序必须相反,我只需在模型上调用相反的方法。
在chapter.get
之前加上minus
chapters.comparator = function(chapter) { return -chapter.get("title"); };