2016-04-14 6 views
1

値の2以上のすべての要素を配列の最後に移動して、整数の配列を並べ替える必要があります。しかし、私が2以上の2つの要素を比較している場合、あるいは両方が2未満の要素を比較している場合、それらを現在の順序で保持したいと考えています。私はネイティブ.sort()と、次の比較関数を使用しています:JS内の一意のネイティブArray.sort()動作

function customSort(a, b) { 
    return (a >= 2 && b < 2) ? 1 : -1; 
} 

次のような場合のために意図したとおりに動作するようです:

[2, 3, 2, 0] => [0, 2, 3, 2] 
[2, 3, 2, 0, 0, 0, 1, 0, 0, 0] => [0, 0, 0, 1, 0, 0, 0, 2, 3, 2] 

しかし、私は過去10個の要素を得れば、それはのように見える、それはランダムに2未満である要素、及び2以上の要素を注文すると思われる:

[2, 3, 2, 0, 0, 0, 1, 0, 0, 0, 0] => [0, 0, 0, 0, 0, 1, 0, 0, 3, 2, 2] 
       (expected result) => [0, 0, 0, 1, 0, 0, 0, 0, 2, 3, 2] 

Iは三元オペラで-1を仮定torは常に左の要素を残しておき、順序を保持します(0とは対照的に、ランダムに順序を決めます)。 .sort()ネイティブを使わずに並べ替えるのが良い方法があることは分かっていますが、私はその動作について興味があり、何らかの方法があればネイティブ.sort()で正しく動作するように比較関数を変更できます。

+0

"ネイティブ"と呼ばれるものは、実際には内蔵されています([*組み込み関数*](http://www.ecma-international.org/ecma-262/6.0/#sec-built-in-関数)または[*組み込みメソッド*](http://www.ecma-international.org/ecma-262/6.0/#sec-built-in-method))。 ECMAScript 2015以前は、[*ネイティブオブジェクト*](http://www.ecma-international.org/ecma-262/5.1/#sec-4.3。6)(関数とメソッドを含む)は、あなたがjavascriptで書くかもしれないものでしたが、この用語は最新の仕様で[*通常のオブジェクト*](http://www.ecma-international.org/ecma -262/6.0 /#sec-ordinary-object)である。 ;-) – RobG

+0

@RobGありがとう、私はあまりにも正しい言葉が何であるかは分かりませんが、知っておいてよかったです! –

+0

これは問題ありません。現時点では、言語仕様は非常に速く変化しています。 – RobG

答えて

1

私はsort方法で何が起こるかのいくつかのコンソールロギングをやったと私は、ソートの反復したアレイ全体、それはどんな要素の上に繰り返すだろうという結論に来ていますあなたの比較関数で再び位置を移動しました。あなたの条件がもう少し具体的で、大規模な配列であるという事実は、何が起こっているのかを追跡することを非常に困難にします。あなたの最初の例を使って、三項演算子と配列の結果をソートしながら記録しました。あなたは、次の取得:

[2, 3, 2, 0] 
-1 
[2, 3, 2, 0] 
-1 
[2, 3, 2, 0] 
1 
[2, 3, 2, 2] 
1 
[2, 3, 3, 2] 
1 
[0, 2, 3, 2] 

並べ替えて[2, 3, 2, 0, 0, 0, 1, 0, 0, 0]、それは29回の反復を通過します。その余分な0を配列の最後に追加すると、58回の反復が行われます。その余分な29の間に私はあなたの条件を使用して要素を前後にシャッフルすると思います。それはあなたが期待している結果を得られない理由を説明するかもしれません。

+0

これを見ていただきありがとうございます!私はconsole.loggingを試しましたが、反復の回数を注意深く見ていませんでした。組み込みの並べ替えを使用するときにこれを調べなければならないと思います。 –

+0

並べ替えがどのように行われたのか不思議でした。これまでのIveでは、配列をソートするために単純な '' a-b''関数を使用していました。最初の例が6回繰り返されたのを見たら(私の考えでは3-4と思っていました)、少し深く掘り下げなければなりませんでした。 – char

2

並べ替えを行わずに実行する方法は、ループしてその1対1の配列や他のアイテムよりも大きなアイテムを別のものに追加して結合することです。 epascarelloの答えと非常に似て

var arr = [2, 3, 2, 0, 0, 0, 1, 0, 0, 0, 0]; 
var shifted = [].concat.apply([],arr.reduce(function (arr, val, ind){ 
               var ind = val > 1 ? 1 : 0; 
               arr[ind].push(val); 
               return arr; 
               }, 
               [[],[]])); 
+0

ありがとう、私は間違いなく.sortの代わりに別の方法を実行しようとしていたが、.sortがこの一貫性のない動作をなぜ生成しているのかと疑問に思っている。 –

1

は、それだけでは後方の配列をループにreduceRightを使用しています。メンバ>= 2に遭遇すると、スプライスされ、配列の最後にプッシュされます。

配列が変更され、新しい配列は作成されませんが、epascarelloは6つの追加配列(concatの結果を含む)を作成します。

var data = [2, 3, 2, 0, 0, 0, 1, 0, 0, 0, 0].reduceRight(function(acc, n, i, data) { 
 
    if (n >= 2) data.push(data.splice(i, 1)); 
 
    return data; 
 
}, null); 
 

 
document.write(data); // [0, 0, 0, 1, 0, 0, 0, 0, 2, 3, 2]

+0

スプライスされた配列を 'data 0、0、0、0、0] => [0、1、2、3、4、0、 0,0,1,0,0,0,0,4,3,2]である。しかし、ありがとう、私は間違いなく逆方向のトラバースのための 'reduceRight'の使用から学んだ –

関連する問題