BACKBONE.JS Iましたがコンパレータ機能で設定コレクションを得ました。モデルをうまく並べ替えていますが、順序を逆にしたいと思います。
モデルを昇順ではなく降順に並べ替える方法を教えてください。
BACKBONE.JS Iましたがコンパレータ機能で設定コレクションを得ました。モデルをうまく並べ替えていますが、順序を逆にしたいと思います。
モデルを昇順ではなく降順に並べ替える方法を教えてください。
回答:
まあ、コンパレータから負の値を返すことができます。たとえば、Backboneのサイトの例を取り上げて、順序を逆にすると、次のようになります。
var Chapter = Backbone.Model;
var chapters = new Backbone.Collection;
chapters.comparator = function(chapter) {
return -chapter.get("page"); // Note the minus!
};
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'));
個人的に、私はここに与えられた解決策のどれにも満足していません:
ソートタイプが非数値の場合、-1による乗算ソリューションは機能しません。これを回避する方法はありますが(Date.getTime()
たとえば、呼び出しによって)、これらのケースは特定のものです。並べ替えられるフィールドの特定のタイプを気にすることなく、並べ替えの方向を逆にする一般的な方法が欲しいのですが。
文字列ソリューションの場合、文字列を一度に1文字ずつ構成すると、特に大きなコレクション(または実際には、大きな並べ替えフィールド文字列)を使用する場合、パフォーマンスのボトルネックのように見えます
以下は、文字列、日付、数値フィールドに対して適切に機能するソリューションです。
最初に、次のように、sortBy関数の結果の結果を逆にするコンパレータを宣言します。
function reverseSortBy(sortByFunction) {
return function(left, right) {
var l = sortByFunction(left);
var r = sortByFunction(right);
if (l === void 0) return -1;
if (r === void 0) return 1;
return l < r ? 1 : l > r ? -1 : 0;
};
}
ここで、並べ替えの方向を逆にしたい場合は、次の操作を行うだけです。
var Chapter = Backbone.Model;
var chapters = new Backbone.Collection;
// Your normal sortBy function
chapters.comparator = function(chapter) {
return chapter.get("title");
};
// If you want to reverse the direction of the sort, apply
// the reverseSortBy function.
// Assuming the reverse flag is kept in a boolean var called reverseDirection
if(reverseDirection) {
chapters.comparator = reverseSortBy(chapters.comparator);
}
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'));
これが機能する理由は Backbone.Collection.sort
、sort関数に2つの引数がある場合の動作が異なるです。この場合、に渡されるコンパレータと同じように動作しArray.sort
ます。このソリューションは、単一引数のsortBy関数を2つの引数のコンパレーターに適合させ、結果を逆にすることで機能します。
Backbone.jsのコレクションコンパレータは、Underscore.jsメソッド_.sortByに依存しています。sortByの実装方法は、文字列を逆にソートすることを困難にする方法でjavascript .sort()を「ラップ」することになります。文字列の単純な否定は、最終的にNaNを返し、ソートを中断します。
アルファベット順の逆順など、文字列を使用した逆順の並べ替えを実行する必要がある場合は、次のようにしてこれを実行するのは本当にハックな方法です。
comparator: function (Model) {
var str = Model.get("name");
str = str.toLowerCase();
str = str.split("");
str = _.map(str, function(letter) {
return String.fromCharCode(-(letter.charCodeAt(0)));
});
return str;
}
決してきれいではありませんが、「文字列否定子」です。JavaScriptでネイティブオブジェクトタイプを変更することに不安がない場合は、文字列否定子を抽出し、それをString.Prototypeのメソッドとして追加することで、コードをより明確にすることができます。ただし、JavaScriptでネイティブオブジェクトタイプを変更すると予期しない結果が生じる可能性があるため、おそらくこれを実行したいのは、自分が何をしているかを知っている場合だけです。
私の解決策は、ソート後に結果を元に戻すことでした。
二重レンダリングがサイレントで最初にソートされるのを防ぐには、「リセット」をトリガーします。
collections.sort({silent:true})
collections.models = collections.models.reverse();
collections.trigger('reset', collections, {});
-Date.getTime()
ます。システムの日付がUNIXエポックを超えると思われる場合は、追加のハッキングを行うことができます。アルファベット順については、上記のアンドリューの答えを見てください。
現在のデータを返す代わりに、逆比例値を返すようにコンパレーター関数を変更します。からのコード:http : //documentcloud.github.com/backbone/#Collection-comparator
例:
var Chapter = Backbone.Model;
var chapters = new Backbone.Collection;
/* Method 1: This sorts by page number */
chapters.comparator = function(chapter) {
return chapter.get("page");
};
/* Method 2: This sorts by page number in reverse */
chapters.comparator = function(chapter) {
return -chapter.get("page");
};
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"}));
以下は私にとってうまくいきました:
comparator: function(a, b) {
// Optional call if you want case insensitive
name1 = a.get('name').toLowerCase();
name2 = b.get('name').toLowerCase();
if name1 < name2
ret = -1;
else if name1 > name2
ret = 1;
else
ret = 0;
if this.sort_dir === "desc"
ret = -ret
return ret;
}
collection.sort_dir = "asc";
collection.sort(); // returns collection in ascending order
collection.sort_dir = "desc";
collection.sort(); // returns collection in descending order
私は、バックボーンコンパレーター関数がJavaScript Array.prototype.sort()関数を使用または模倣している箇所をいくつか読みました。つまり、1、-1、または0のいずれかを使用して、コレクション内の各モデルの並べ替え順序を決定します。これは常に更新され、コレクションはコンパレーターに基づいて正しい順序で維持されます。
Array.prototype.sort()に関する情報はここにあります:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?redirectlocale=en-US&redirectslug=JavaScript% 2FReference%2FGlobal_Objects%2FArray%2Fsort
この質問に対する多くの回答は、ページに表示する直前に順序を逆にするだけです。これは理想的ではありません。
上記のMozillaに関する記事をガイドとして使用して、次のコードを使用してコレクションを逆順に並べ替えておくことができました。その後、コレクションを現在の順序でページにレンダリングし、フラグ(reverseSortDirection)を使用して順序を逆にすることができます。 。
//Assuming this or similar will be in your Backbone.Collection.
sortKey: 'id', //The field name of the item in your collection
reverseSortDirection: false,
comparator: function(a, b) {
var sampleDataA = a.get(this.sortKey),
sampleDataB = b.get(this.sortKey);
if (this.reverseSortDirection) {
if (sampleDataA > sampleDataB) { return -1; }
if (sampleDataB > sampleDataA) { return 1; }
return 0;
} else {
if (sampleDataA < sampleDataB) { return -1; }
if (sampleDataB < sampleDataA) { return 1; }
return 0;
}
},
2つのモデルを除くコンパレータ。コレクションまたはモデルへの変更時に、comparor関数が実行され、コレクションの順序が変更されます。
私はこのアプローチをNumbersとStringsでテストしましたが、完全に機能しているようです。
私がこの問題に何度も取り組み、通常は回避策を講じることになるので、この答えが役に立てば幸いです。
sortKey
しreverseSortDirection
て呼び出すことができます.sort()
。他の投票数の多い回答よりも単純です。
これは、sortByメソッドをオーバーライドすることにより、エレガントに行うことができます。ここに例があります
var SortedCollection = Backbone.Collection.extend({
initialize: function () {
// Default sort field and direction
this.sortField = "name";
this.sortDirection = "ASC";
},
setSortField: function (field, direction) {
this.sortField = field;
this.sortDirection = direction;
},
comparator: function (m) {
return m.get(this.sortField);
},
// Overriding sortBy (copied from underscore and just swapping left and right for reverse sort)
sortBy: function (iterator, context) {
var obj = this.models,
direction = this.sortDirection;
return _.pluck(_.map(obj, function (value, index, list) {
return {
value: value,
index: index,
criteria: iterator.call(context, value, index, list)
};
}).sort(function (left, right) {
// swap a and b for reverse sort
var a = direction === "ASC" ? left.criteria : right.criteria,
b = direction === "ASC" ? right.criteria : left.criteria;
if (a !== b) {
if (a > b || a === void 0) return 1;
if (a < b || b === void 0) return -1;
}
return left.index < right.index ? -1 : 1;
}), 'value');
}
});
したがって、次のように使用できます。
var collection = new SortedCollection([
{ name: "Ida", age: 26 },
{ name: "Tim", age: 5 },
{ name: "Rob", age: 55 }
]);
//sort by "age" asc
collection.setSortField("age", "ASC");
collection.sort();
//sort by "age" desc
collection.setSortField("age", "DESC");
collection.sort();
このソリューションはフィールドタイプに依存しません。
これは、現在の順序を逆にしたいだけの人のための、本当にシンプルなソリューションです。列が2方向に配列できるテーブルがある場合に便利です。
collection.models = collection.models.reverse()
テーブルケース(コーヒースクリプト)に興味がある場合は、次のようなものと組み合わせることができます。
collection.comparator = (model) ->
model.get(sortByType)
collection.sort()
if reverseOrder
collection.models = collection.models.reverse()
テーブルにモデルを表示しているという点で少し異なる要件があり、それらを任意の列(モデルプロパティ)で昇順または降順でソートできるようにしたかったのです。
すべてのケースを機能させるにはかなりの手間がかかります(値は文字列、空の文字列、日付、数値の場合があります。しかし、これはかなり近いと思います。
inverseString: function(str)
{
return str.split("").map(function (letter) { return String.fromCharCode(-(letter.charCodeAt(0))); }).join("");
}
getComparisonValue: function (val, desc)
{
var v = 0;
// Is a string
if (typeof val === "string")
{
// Is an empty string, upgrade to a space to avoid strange ordering
if(val.length === 0)
{
val = " ";
return desc ? this.inverseString(val) : val;
}
// Is a (string) representing a number
v = Number(val);
if (!isNaN(v))
{
return desc ? -1 * v : v;
}
// Is a (string) representing a date
v = Date.parse(val);
if (!isNaN(v))
{
return desc ? -1 * v : v;
}
// Is just a string
return desc ? this.inverseString(val) : val;
}
// Not a string
else
{
return desc ? -1 * val : val;
}
},
使用する:
comparator: function (item)
{
// Store the collumn to 'sortby' in my global model
var property = app.collections.global.get("sortby");
// Store the direction of the sorting also in the global model
var desc = app.collections.global.get("direction") === "DESC";
// perform a comparison based on property & direction
return this.getComparisonValue(item.get(property), desc);
},
sort関数をオーバーライドして、完了時にモデル配列を逆にします。また、リバースが完了するまで、「ソート」イベントのトリガーを保留しました。
sort : function(options){
options = options || {};
Backbone.Collection.prototype.sort.call(this, {silent:true});
this.models.reverse();
if (!options.silent){
this.trigger('sort', this, options);
}
return this;
},
最近この問題に遭遇し、rsortメソッドを追加することにしました。
Collection = Backbone.Collection.extend({
comparator:function(a, b){
return a>b;
},
rsort:function(){
var comparator = this.comparator;
this.comparator = function(){
return -comparator.apply(this, arguments);
}
this.sort();
this.comparator = comparator;
}
});
うまくいけば、誰かがこれが役に立つと思うでしょう
UnderscoreJSを使用してコレクションのモデルを逆ソートする迅速かつ簡単な方法を次に示します
var reverseCollection = _.sortBy(this.models, function(model) {
return self.indexOf(model) * -1;
});