javascript 使用backbone.js以相反的顺序对字符串进行排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5636812/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sorting strings in reverse order with backbone.js
提问by Emil Stenstr?m
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.
我正在尝试以相反的顺序对 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'));
The above code sorts the chapters from A -> Z, but how do I write a comparator that sorts it from Z -> A?
上面的代码从 A -> Z对章节进行排序,但是如何编写一个比较器从 Z -> A对其进行排序?
采纳答案by Dan Smart
There are two versions of the comparator function that you can use, either the sortByversion - which was shown in the example, which takes one parameter, or sort- which you can return a more standard sort function, which the documentationsays:
您可以使用两种版本的比较器函数,一种是sortBy版本 - 在示例中显示,它采用一个参数,或者sort- 您可以返回一个更标准的排序函数,文档说:
"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.
“sortBy”比较器函数采用一个模型并返回一个数字或字符串值,该模型应该相对于其他模型进行排序。“排序”比较器函数采用两个模型,如果第一个模型应该在第二个模型之前,则返回 -1,如果它们的等级相同,则返回 0,如果第一个模型应该在之后,则返回 1。
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"
回答by Filip Salomonsson
You could:
你可以:
- grab the char code for each character in the string,
- subtract each value from
0xffff
(the maximum return value ofstring.charCodeAt
), - use
String.fromCharCode
to turn that back into string of "negated" characters
- 获取字符串中每个字符的字符代码,
- 从
0xffff
(的最大返回值string.charCodeAt
)中减去每个值, - 用于
String.fromCharCode
将其转回“否定”字符字符串
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.
注意:如果您的比较字符串很长(如 65 kb 或更多),您可能会遇到麻烦(请参阅下面的 Matt 评论)。为了避免这种情况,并稍微加快比较,只需使用比较字符串的较短片段。(在上面的示例中,您可以chapter.get("title").slice(0, 100).split("")
改为使用。)您需要多长时间的切片将取决于您的应用程序。
回答by Gary Chambers
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:
如果您正在处理非数字值,则没有明显的方法可以进行反向排序。Backbone 使用Underscore的_.sortBy()
和_.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();
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.
这不会影响您的 Backbone 集合中的模型数组,因为它会在内存中创建一个全新的结果数组,但保留对原始模型的引用,因此调用类似的东西save
仍然会更新集合状态。
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:
为了使这项工作,您需要在您的比较器方法中执行一些笨拙的 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;
};
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.
这个概念可能需要改进以考虑符号等,但本质上它以“Z”变为“0”,“Y”变为“1”等的方式反转比较器字符串,这应该会产生相反的结果排序你所追求的。
回答by Kelley van Evert
As Backbone merely uses the .sortBy method, simply proxy in your own logic:
由于 Backbone 仅使用 .sortBy 方法,因此只需在您自己的逻辑中进行代理:
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: [...] })
回答by David Fregoli
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.
在这种情况下,我只是将比较器设置为字符串而不是函数;该字符串必须是您要作为排序依据的属性的名称。然后,如果顺序必须相反,我只需在模型上调用 reverse 。
回答by openlab
Just add minus before chapter.get
之前加减号 chapter.get
chapters.comparator = function(chapter) {
????return -chapter.get("title");
};