underscore.jsを使用してascおよびdescソートを実行するにはどうすればよいですか?


166

私は現在、jsonの並べ替えにアンダースコアを使用しています。今度は、underscore.jsを使用してascendingdescending並べ替えを行うように依頼しました。ドキュメンテーションでは同じことについて何も見ていません。どうすればこれを達成できますか?


1
並べ替えの対象と方法の例を追加してください。
Jon

何を選別していますか?数字?文字列?日付?他に何か?
muが短すぎる

@muistooshortオブジェクトの配列を並べ替えています。したがって、sortByメソッドは昇順の並べ替えでは完全に私の基準に適合しますが、逆の順序では適合しません。
Rahul

数値で並べ替える場合、sortBy関数は可能ですreturn -nが、文字列では機能しません。したがって、どのような種類のものを並べ替えるかについての質問です。
muが短すぎる

2
Lodashでは、配列のプロトタイプを使用したくない場合_.sortBy([1,4,3,2]).reverse()_.chain([1,4,3,2]).sortBy().reverse().value()、省略したい場合に使用できますreverse()
GFoley83 2014

回答:


363

を使用できます.sortBy。常に昇順のリストが返されます。

_.sortBy([2, 3, 1], function(num) {
    return num;
}); // [1, 2, 3]

ただし、.reverseメソッドを使用して降順で取得できます。

var array = _.sortBy([2, 3, 1], function(num) {
    return num;
});

console.log(array); // [1, 2, 3]
console.log(array.reverse()); // [3, 2, 1]

または、数値を扱うときは、リストに降順で戻るために負の符号を追加します。

_.sortBy([-3, -2, 2, 3, 1, 0, -1], function(num) {
    return -num;
}); // [3, 2, 1, 0, -1, -2, -3]

ボンネットの下には.sortByビルトインが使用されてい.sort([handler])ます:

// Default is ascending:
[2, 3, 1].sort(); // [1, 2, 3]

// But can be descending if you provide a sort handler:
[2, 3, 1].sort(function(a, b) {
    // a = current item in array
    // b = next item in array
    return b - a;
});

9
最後の解決策、つまり返されたnumに否定的な記号を追加することは完璧です。
vinesh 2014年

なぜバブルソートだと思いますか?内部での.sortBy()呼び出しは組み込みでありArray.sort()、そのアルゴリズムはブラウザーベンダー次第ですが、バブルソートが選択されることはほとんどありません。
Rene Saarsoo、2015

これは時間の複雑さを増しませんか?リストが2回ソートされます。
user1477388 2016

@ user1477388 2回ソートする意味がわからない?
andlrc

@andlrcしたがって、を呼び出すと_.sortBy(arr, function)、各項目をループし、いくつかのロジックを実行して、ソートされた配列を返すと想定します。次に、Array.prototype.reverse()それを呼び出すと、おそらく各項目が再びループされ、逆の配列を返すためのロジックが実行されます。したがって、配列を2回ループしています。
user1477388

57

アンダースコアを使用した降順は、戻り値に-1を乗算することで実行できます。

//Ascending Order:
_.sortBy([2, 3, 1], function(num){
    return num;
}); // [1, 2, 3]


//Descending Order:
_.sortBy([2, 3, 1], function(num){
    return num * -1;
}); // [3, 2, 1]

数値ではなく文字列で並べ替える場合は、charCodeAt()メソッドを使用してUnicode値を取得できます。

//Descending Order Strings:
_.sortBy(['a', 'b', 'c'], function(s){ 
    return s.charCodeAt() * -1;
});

3
私はアルファベット順にソートしようとしています--1を掛けることは有効な演算ではありません。:)
rythos42 2013年

ユースケースとしては価値がありますが、質問では指定されていません。ただし、文字列に-1を掛けることは有効な演算です。有効な結果であるNaNを返します。
jEremyB 2013年

1
配列も忘れずに割り当ててください!SOME_ARR = _.sortBy(SOME_ARR、function(num){SOME_FUNC ...});
aqm 2014年

4
charCodeAtは「文字列内の指定されたインデックスにある文字のUnicodeを返す」ため、文字列内の文字で並べ替えることができますが、「文字列で並べ替える」ことはできず、文字列内の文字で並べ替えられます
アンソニー

2
これは最初の文字のみで並べ替え、大文字と小文字を区別します。
エイダン2014

50

アレイの試作品のリバース方式の修正アレイと、あなたがこれを行うことができますどの手段、それへの参照を返します。

var sortedAsc = _.sortBy(collection, 'propertyName');
var sortedDesc = _.sortBy(collection, 'propertyName').reverse();

また、アンダースコアのドキュメントには次のように記載されています。

さらに、ArrayプロトタイプのメソッドはチェーンされたUnderscoreオブジェクトを介してプロキシされるため、a reverseまたはa pushをチェーンに入れ、配列の変更を続けることができます。

つまり.reverse()、連鎖中にも使用できます。

var sortedDescAndFiltered = _.chain(collection)
    .sortBy('propertyName')
    .reverse()
    .filter(_.property('isGood'))
    .value();

これは、最も単純なユースケースに関して、逆/降順の並べ替えの最も簡単な方法です。
Dan Atkinson

2
:大文字と小文字を区別しないアルファベット順の並べ替えを行うには_.sortBy(collection, item => item. propertyName.toLowerCase());
- XåpplI'-I0llwlg'I

配列に負の数がある場合、これは機能しません。
Shruti Kapoor 2016

@ShrutiKapoorはい、あります。なぜでしょうか?
Emil Lundberg

5
パフォーマンスに関しては、最初にフィルターを適用し、次に(残りの)値をソートすることが望ましいでしょう。
サラン2017年

12

Underscoreライブラリーと同様に、「lodash」と呼ばれる別のライブラリーがあります。これには、パラメーターを受け取ってソートする順序を決定する「orderBy」という1つのメソッドがあります。こんな風に使えます

_.orderBy('collection', 'propertyName', 'desc')

何らかの理由で、ウェブサイトのドキュメントに記載されていません。


アンダースコアlodashを混同していると思います。後者だけが、前述のorderBy関数を持っています
Thomas Marti 2017

うん、悪いわ。答えを更新します。修正してくれてありがとう:)
Minkesh Jain

orderBy、超便利!私が探している安定したソートプロパティを保持するため、reverseを使用するよりもはるかに優れています。
Flimm 2017

何らかの理由で私のために働いていないupadte:そのlodash(
aleXela

0

アンダースコアミックスイン

@emil_lundbergの答えを拡張して、アンダースコアを使用してソートのカスタム関数を作成している場合は、「ミックスイン」を記述して、アプリケーションのどこかで繰り返す可能性のあるソートである場合は、それを行うこともできます。

たとえば、「ASC」または「DESC」の並べ替え順序でコントローラーまたはビューの並べ替え結果を表示していて、その並べ替えを切り替える場合は、次のようにします。

Mixin.js

_.mixin({
    sortByOrder: function(stooges, prop, order) {
      if (String(order) === "desc") {
          return _.sortBy(stooges, prop).reverse();
      } else if (String(order) === "asc") {
          return _.sortBy(stooges, prop);
      } else {
          return stooges;
      }
    }
})

使用例

var sort_order = "asc";
var stooges = [
  {name: 'moe', age: 40}, 
  {name: 'larry', age: 50}, 
  {name: 'curly', age: 60},
  {name: 'July', age: 35},
  {name: 'mel', age: 38}
 ];

_.mixin({
    sortByOrder: function(stooges, prop, order) {
    if (String(order) === "desc") {
        return _.sortBy(stooges, prop).reverse();
    } else if (String(order) === "asc") {
        return _.sortBy(stooges, prop);
    } else {
        return stooges;
    }
  }
})


// find elements
var banner = $("#banner-message");
var sort_name_btn = $("button.sort-name");
var sort_age_btn = $("button.sort-age");

function showSortedResults(results, sort_order, prop) {
    banner.empty();
    banner.append("<p>Sorting: " + prop + ', ' + sort_order + "</p><hr>")
  _.each(results, function(r) {
    banner.append('<li>' + r.name + ' is '+ r.age + ' years old.</li>');
  }) 
}

// handle click and add class
sort_name_btn.on("click", function() {
  sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'name', sort_order);
  showSortedResults(sortedResults, sort_order, 'name');
})

sort_age_btn.on('click', function() {
    sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'age', sort_order);
  showSortedResults(sortedResults, sort_order, 'age');
})

これを示すJSFiddleは次のとおりです。JSFiddlefor SortBy Mixin

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.