• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:【ActionScript】配列の昇順降順混合の複合ソートはできますか?)

【ActionScript】配列の昇順降順混合の複合ソートはできますか?

このQ&Aのポイント
  • FLASH8(Win-XP)使用者です。配列の複合ソートを昇順降順おりまぜてしたいのですが可能でしょうか?下記のスクリプトですと、高さも幅も降順になります。しかし実際には高さは降順、幅は昇順にしたいのです。
  • myArrayという配列に高さと幅の情報があり、これを昇順降順を組み合わせてソートしたいです。
  • 現在のスクリプトでは、高さと幅の両方が降順にソートされますが、高さは降順、幅は昇順にしたいです。解決方法を教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • DPE
  • ベストアンサー率85% (666/776)
回答No.3

sortOn の条件は数値でも指定できます。 ・・・というよりも、Array.NUMERIC などがそもそも、フラグの意味を分かりやすくするために用意されている定数にすぎません。 いうなれば、Math.PI と書くと円周率の近似値 3.1415…と解釈されるけれど、数値で直接 3.1415…と書くこともできるのと、同じ話です。 デフォルトの「文字コード順に」「昇順」でソートするための定数は定義されていませんが、どのフラグも立てないデフォルトの条件とは、数値にすると 0 です。 つまり 0 を渡すと、条件の指定なしということでデフォルトの「文字コード順に」「昇順」のソートになります。 「文字コード順に」「降順」でソートする時は Array.DESCENDING を渡します。 定数で書けず数値でしか表現できない条件は、デフォルトの「文字コード順に」「昇順」のソートだけですね。 例えば、 (↓各行頭に全角のスペースが入っています。コピーする際はご注意ください)  myArray =  [   { h : 20 , material : "マツ" , w : 10 } ,   { h : 100 , material : "ラワン" , w : 20 } ,   { h : 40 , material : "ヒノキ" , w : 15 } ,   { h : 20 , material : "ラワン" , w : 10 } ,   { h : 20 , material : "ヒバ" , w : 20 } ,   { h : 40 , material : "ヒノキ" , w : 40 } ,   { h : 20 , material : "スギ" , w : 25 } ,   { h : 40 , material : "マツ" , w : 20 }  ]; このような配列変数があり、これを  ・高さ( h )については「数値の順に降順」  ・材質( material )については「文字コードの順に昇順」  ・幅( w )については「数値の順に昇順」 という条件でソートするとします。 フィールドごとに条件を指定する sortOn では、フィールドの数と条件の数が一致していなければなりません。 中央の” material ”フィールドはデフォルトの条件でいいのですが、  myArray.sortOn( [ "h" , "material" , "w" ] , [ Array.NUMERIC | Array.DESCENDING , , Array.NUMERIC ] ); ↑こう書くと、当然ながらエラーになってしまいます。 そこで、” material ”フィールドの条件には、どのフラグも立てない 0 を渡します。  myArray.sortOn( [ "h" , "material" , "w" ] , [ Array.NUMERIC | Array.DESCENDING , 0 , Array.NUMERIC ] ); 裏ワザのようですけれど、文字列が格納されているフィールドでは NUMERIC フラグは無視されるだけなので、NUMERIC をダミーとして詰めておくのも1つの手です。 ただし、数値が入っているフィールドをあえて「文字コード順に」「昇順」でソートする場合は通用しません。このような場合は 0 を指定してください。 ----------------------------------------------------------------- 冒頭にも書きましたように、sortOn の条件の指定に使う Array クラスの NUMERIC や DESCENDING は定数で、それぞれ決まった数が定義されています。 定数の内容は次の通りです。 ( )内が、定義されている数値です  ・CASEINSENSITIVE( 1 )    大文字・小文字を区別せずにソートします。  ・DESCENDING( 2 )    降順にソートします。  ・UNIQUESORT( 4 )    全く同じ条件のものがあった時に、ソートを中断します。  ・RETURNINDEXEDARRAY( 8 )    元の配列の並び方を変えず、並び替えた後の順番だけを取得できます。  ・NUMERIC( 16 )    数値の大小で比較します。文字列のフィールドでは無効です。 例えば「数値の大小で」「昇順」のソートは  myArray.sortOn( "w" , 16 ); と書くよりも  myArray.sortOn( "w" , Array.NUMERIC ); の方が、”数値で比較するソート”であることが分かりやすくなります。 Array.NUMERIC は 16 のことですから、数値で書いても Array クラスで定義されている定数で書いても意味は全く同じです。 複数の条件を指定する場合も同様で、例えば「数値の大小で」「降順」にソートする条件は  Array.NUMERIC | Array.DESCENDING というように書きますが、これは  16 | 2 として解釈されます。 16 | 2 の計算結果は 18 です。 NUMERIC や DESCENDING の代わりに 18 を直接渡してもいいですし、もちろん 16 | 2 と書くこともできます。 OR 演算がよく分からない時は、trace アクションを使って  trace( Array.NUMERIC | Array.DESCENDING ); で、結果が分かります。 Windows に付いている「電卓」は、関数電卓モードにすると OR やその他のビット演算も計算できます。 定数を使うと分かりやすくはなるのですが、全て大文字である上に概して名前が長く、複数の条件を組み合わせるなど条件の数が多い時はかえって見にくくなるのも事実です。 場合によって、数値の指定と使い分けてください。 ただ、数値で指定するとスクリプトが短くスッキリまとまるものの、意味は分かりにくくなります。 後で見た時に「どんな条件のソートだったかな?」とならないように、コメントを入れておくといいですよ。

ikataro
質問者

お礼

う~ん、なるほど! 0を使うのですか。 配列も実に奥が深いですね。 このたびは感動の3連発本当にお世話になりました。

その他の回答 (2)

  • DPE
  • ベストアンサー率85% (666/776)
回答No.2

#1です。 まず、訂正なのですが。 フィールドごとに条件を変える時の sortOn は、正確には  myArray.sortOn( [ "takasa" , "haba" ] , [ Array.NUMERIC | Array.DESCENDING , Array.NUMERIC ] ); でした。 #1の書き方ですと、takasa のフィールドが文字コード順のソートになります。 今回の例はどれも同じく2桁の数値なので文字コード順でも何とか上手くいくのですが、例えば takasa に 100 が入っている場合、降順で最も先になるはずが最後になってしまいます。 数値の大小でソートするなら、NUMERIC フラグを渡して明示的に数値として比較するべきですね。 失礼いたしました。 ------------------------------------------------------------------- もう1点は補足です。 sortOn は、デフォルトでは「文字コード順に」「昇順」のソートです。 つまり、何も指示しなければ昇順のソートであり、数値が入っている場合であっても文字コード順で比較されます。 NUMERIC フラグを渡すと、文字コード順ではなく数値の大小で比較されるようになります。 ですから、NUMERIC フラグだけを渡した場合は「数値の大小で」「昇順」のソートになります。 NUMERIC フラグが”昇順でソートせよ”との意味を持っているのではありません。 デフォルトで昇順のソートなので、あえて昇順を指示するフラグは必要ないということだと思います。 DESCENDING は”降順に”ソートするように指示するフラグです。 従って、このフラグだけを渡すと「文字コードの順に」「降順」のソートに、NUMERIC フラグとともに渡すと「数値の大小で」「降順」のソートになります。 NUMERIC フラグの逆の意味が DESCENDING フラグなのではありません。 説明が足りず誤解を招いてしまったようで、重ね重ね失礼いたしました。 この場をお借りしまして、訂正・補足させていただきます。 Array クラスが持っている DESCENDING や NUMERIC はスイッチのようなもので、渡すフラグの組み合わせでソートの条件が変化します。 ビット演算の OR (演算子” | ”)で、複数のフラグを組み合わせることができます。 他にもいろいろな組み合わせがありますので、機会がありましたら使ってみてください。

ikataro
質問者

お礼

めんどうな質問に付き合っていただきありがとうございます。 そういうことですか。これは勉強になります。 しかしここで新たな疑問が… [ Array.NUMERIC | Array.DESCENDING , Array.NUMERIC ] の右部分が仮に「文字コード順に」だったら書くものがない… [ Array.NUMERIC | Array.DESCENDING , ] と書くわけには? 明示するものがないというのはなんか困るような・・

  • DPE
  • ベストアンサー率85% (666/776)
回答No.1

まず、配列変数の各フィールドの値が数値ではなく文字列になっていますが、何か事情があるのでしょうか? 文字列が入っている場合は数値として判断する NUMERIC フラグが無効になり、必ず文字コードの順にソートされます。 文字コードの順とは、例えば 1 ・ 2 ・ 11 を昇順にソートすると、2 が 11 よりも大きいと判断されて 1 → 11 → 2 の順になるということです。 数値の大小でソートする時に NUMERIC フラグが使えないととても不便ですから、特に事情がないのなら最初から数値を入れる方が得策です。 以下は、各フィールドに数値を入れた場合の話です。 数値を入れる時は  myArray.push( { takasa : 20 , haba : 40 } );  myArray.push( { takasa : 20 , haba : 20 } );   : というように、数値を " " でくくらずに入れてください。 Flash Player 8 からは、配列変数のフィールドごとにソートの条件を指定できるようになりました。 sortOn の部分を  myArray.sortOn( [ "takasa" , "haba" ] , [ Array.DESCENDING , Array.NUMERIC ] ); このように変更してみてください。 trace アクションの結果は次のようになります。  高=40 幅=10  高=40 幅=15  高=40 幅=20  高=20 幅=15  高=20 幅=20  高=20 幅=40 takasa については降順で、 haba については昇順に並びます。 つまり、takasa に同じ値が複数ある場合は haba の値が小さいものが先になります。 takasa に同じ値がない時は takasa の降順ソートが優先されます。 ------------------------------------------------------------------ 単純に、takasa を見る時は降順・ haba を見る時は昇順で、同値の時に相方のフィールドの大小を問わないのであれば、その都度 sortOn を実行するか、元の配列を変更しない RETURNINDEXEDARRAY フラグを指定して並べ替えた後のリストを2種類用意すれば済みます。 RETURNINDEXEDARRAY フラグを使った作例は以前別の質問で紹介しましたので、よろしければご参照ください。 #2で説明しております。  ・配列操作   http://okwave.jp/qa1061651.html 今回の例で言いますと、takasa について降順で並べ替えたリストと haba について昇順で並べ替えたリストを2つ用意します。 (↓各行頭に全角のスペースが入っています。コピーする際はご注意ください)  //オリジナルの配列変数  myArray = new Array;  //takasaとhabaのソート結果を保持する配列変数  t_list = new Array();  h_list = new Array();  //オリジナルの配列変数の中身  myArray.push( { takasa : 20 , haba : 40 } );  myArray.push( { takasa : 20 , haba : 20 } );  myArray.push( { takasa : 40 , haba : 10 } );  myArray.push( { takasa : 20 , haba : 15 } );  myArray.push( { takasa : 40 , haba : 20 } );  myArray.push( { takasa : 40 , haba : 15 } );  //takasaについては降順、habaについては昇順のリストを作る  t_list = myArray.sortOn( "takasa" , Array.NUMERIC | Array.DESCENDING | Array.RETURNINDEXEDARRAY );  h_list = myArray.sortOn( "haba" , Array.NUMERIC | Array.RETURNINDEXEDARRAY );  //ソートの結果を出力  trace( "-- takasaの大きい順に表示 --" );  for( i = 0 ; i < t_list.length ; i++ )  {   trace( "Index=" + t_list[ i ] + " 高=" + myArray[ t_list[ i ] ].takasa + " 幅=" + myArray[ t_list[ i ] ].haba );  }  trace( "\n-- habaの小さい順に表示 --" );  for( i = 0 ; i < h_list.length ; i++ )  {   trace( "Index=" + h_list[ i ] + " 高=" + myArray[ h_list[ i ] ].takasa + " 幅=" + myArray[ h_list[ i ] ].haba );  } trace アクションの結果は次のようになります。  -- takasaの大きい順に表示 --  Index=5 高=40 幅=15  Index=4 高=40 幅=20  Index=2 高=40 幅=10  Index=3 高=20 幅=15  Index=1 高=20 幅=20  Index=0 高=20 幅=40  -- habaの小さい順に表示 --  Index=2 高=40 幅=10  Index=5 高=40 幅=15  Index=3 高=20 幅=15  Index=1 高=20 幅=20  Index=4 高=40 幅=20  Index=0 高=20 幅=40 ” Index ”は元の配列( myArray )のインデックス番号です。この番号が、t_list および h_list の中に入っています。 元の配列変数の並びは変わっていません。 希望の条件で並べ替えた後のリストだけ複数用意しておくと、どのような順番でも表示できます。 sortOn に渡すフラグが長くなって見辛いのであれば、ビット演算の結果を数値で渡すこともできます。 先の例では  //takasaについては降順、habaについては昇順のリストを作る  t_list = myArray.sortOn( "takasa" , 26 );  h_list = myArray.sortOn( "haba" , 24 ); としても同様の結果になります。 Array クラスのソートは、デフォルトでは数値であっても”文字コード順”です。 今回の件ではどの値も一律2桁で、文字コードの順にソートされても影響はありませんが、各数値の桁が異なる場合は特に NUMERIC フラグを渡さないと大小の判断が正しくなくなることがありますので、ご注意ください。

ikataro
質問者

お礼

なるほど!! ""は余計でしたね・・ DESCENDINGの逆はNUMERICだったとは知りませんでした。 専門書は何冊かありますがこのような解説はありませんでした。 もっと詳しい本を探した方が良さそうですね・・ 感謝、ありがとうございました。

関連するQ&A