Emi*_*röm 40 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'));
Run Code Online (Sandbox Code Playgroud)
上面的代码对A - > Z的章节进行了排序,但是如何编写一个比较器,从Z - > A中对它进行排序?
Fil*_*son 45
你可以:
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();
})
);
}
Run Code Online (Sandbox Code Playgroud)
瞧:
> console.log(chapters.pluck('title'));
["The Middle", "The End", "The Beginning"]
Run Code Online (Sandbox Code Playgroud)
注意:如果您的比较字符串很长(如65 kb或更高),您可能会遇到麻烦(请参阅下面的Matt评论).为了避免这种情况,并加快比较速度,只需使用比较字符串的较短切片.(在上面的示例中,您可以chapter.get("title").slice(0, 100).split("")改为使用.)您需要多长时间取决于您的应用程序.
Dan*_*art 20
您可以使用比较器函数的两个版本,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'));
Run Code Online (Sandbox Code Playgroud)
所以你应该作为回应:
"The Middle", "The End", "The Beginning"
Run Code Online (Sandbox Code Playgroud)
Gar*_*ers 12
如果您使用的是非数值,则没有明显的方法可以进行反向排序.Backbone利用Underscore中的_.sortBy()and和_.sortedIndex()方法根据比较器对模型进行排序,这些方法会自动按升序排序.这种天真的方法是使用chapters.pluck('title').reverse(),因为pluck它将是一个数组.但是调用reverse一些Collection方法会将Collection模型反转到位,所以下次调用它时,模型将按升序返回.你总是可以这样做:
var results = [],
titles = chapters.pluck('title');
for(var i=0, len=titles.length; i<len; i++) {
results.push(titles[i]);
}
results.reverse();
Run Code Online (Sandbox Code Playgroud)
这不会影响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;
};
Run Code Online (Sandbox Code Playgroud)
这个概念可能需要改进以考虑符号等,但实际上它以"Z"变为"0","Y"变为"1"等方式反转比较器串,这应该产生相反的你想要点什么.
小智 12
由于Backbone只使用.sortBy方法,只需在您自己的逻辑中进行代理:
collectionInQuestion.sortBy = function () {
var models = _.sortBy(this.models, this.comparator);
if (forSomeReason) {
models.reverse();
}
return models;
};
Run Code Online (Sandbox Code Playgroud)
..或者把它添加到其他地方..
TweakedCollection = Backbone.Collection.extend({ sortBy: [...] })
Run Code Online (Sandbox Code Playgroud)