• ベストアンサー

「降順ソート⇒次に=だった場合はランダム」で抽出したい。

perlの初心者です・・・。 以下の商品にそれぞれポイントが入っていて、 そのポイントを基準に、ランキング形式(降順で)で並ばせたいのです。 my %options = ( apple => 3, banana => 1, melon => 1, peach => 9, ); my @op_rank = sort{scalar($options{$b}) <=> scalar($options{$a})} keys %options; 自分なりに降順にするまでは書くことが出来たのですが、 もしポイントが同じものがあった場合に、ランダムで並び替えをするやり方がわかりません。 別のサブルーチンに分かれてもよいので、できるだけシンプルにかける方法がありましたら教えてください。お願いします。

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

  • ベストアンサー
  • g_p_
  • ベストアンサー率53% (28/52)
回答No.2

my @op_rank = sort{ scalar($options{$b}) <=> scalar($options{$a}) or rand() <=> rand() } keys %options; これじゃだめですかね。

mekapan
質問者

お礼

す、すごい!!ありがとうございます!!! 同点のものがちゃんとランダムで入れ替わりました。 これの意味をちゃんと理解せねば・・・

mekapan
質問者

補足

g_p_さんの書いたコードは scalar($options{$b}) <=> scalar($options{$a}) の部分で比較して、もし=だったものに関しては並び替えが発生しないので、 or rand() <=> rand() の部分に引っかかり、ランダムに入れ替えが発生している? ということですよね?? この一文が思いつかないですよ!! rand()同士で比較させて入れ替わるっていう部分がちょっと理解に苦しみますが・・・。

その他の回答 (2)

  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.3

No.1 です。 > ソートとランダムを別々に考えるのならできるのですが。 > 同時に書く書き方が分からないです。 同時に書くのは難しいでしょうね。 ソートを終わってからサーチして同じものの連続を探し、ランダム化するというのが普通のやり方だと思いますが。 そうしないとプログラムの保守性も悪くなると思います。

  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.1

考え方だけ書きます。 ソート後同じポイントがN個有るとするとN枚のトランプのシャッフルを考えればいいですね。 1.乱数で任意の2枚を選んで交換しこれを複数回繰り返す。 2.乱数で任意の1枚を選んでトップと交換しトップを除いて同じことを次々と続ける。   残りが1枚になったらソート完了。 1の方が簡単ですが、2の方がスマートで私は2をよく使います。 ただこれらの方法は必ずしも完全ランダムは得られないようですが実用上は問題ありません。

mekapan
質問者

補足

正直混乱してます・・・。 ソートとランダムを別々に考えるのならできるのですが。 同時に書く書き方が分からないです。 時間がないので、ゆっくり考えてられません。

関連するQ&A