2016-04-27 8 views
1

配列の配列を扱っています。私は行をソートする必要があり、ソート基準は左から順に各列(2列目から始まる)の値です。無限の値は底部にプッシュする必要があります。一度底に押し込まれると、連続した検索が互いの位置を変えずにそのままの状態で列を残す必要があります。この配列で始まる:nilの位置を変更しないRuby配列のソート

sort_array = 
[[297, 100, 101, 235, 253, nil, nil, nil], 
[286, 116, 116, 213, nil, nil, nil, nil], 
[256, 105, 111, 212, 216, 264, nil, nil], 
[276, 108, 111, 204, 207, 257, 259, 367], 
[274, 66, 66, 120, 121, nil, 150, nil], 
[298, 114, 117, 270, 270, nil, nil, nil], 
[296, 127, 130, 259, 264, 324, 332, nil], 
[283, 102, 106, 193, 199, 247, 248, 343]] 

Iは、これらのコード行を有するアレイを横切って反復:

(1..sort_array[0].size - 1).each do |i| 
    sort_array.sort_by! { |e| [e[i] ? 0 : 1, e[i]] } 
end 

アイデアは、最初の列を無視するが、押し込み昇順にn列を介して第2のソート下限にnil値。これにより、次の結果が得られます。

これは、私が必要とするものに近いものの、かなり正しいものではありません。問題は一度底にプッシュされたゼロ値が置かれていないことです。

=> [[283, ... 247, ...] 
    [276, ... 257, ...] 
    [256, ... 264, ...] 
    [296, ... 324, ...] 
    [297, ... nil, ...] 
    [274, ... nil, ...] 
    [298, ... nil, ...] 
    [286, ... nil, ...] 

をしかし、さらにソートを台無しに並べ替えされるゼロ値の右結果に列のソート:例えば、その最初の値が247である列を並べ替えた後、アレイは、このように見えたであろう。右側のセルがnilでない場合は、Nilの値をそのままにしておく必要があります。この場合、通常のようにソートする必要があります。ソートが終了すると、テーブルは次のようになります。

=> [[283, 102, 106, 193, 199, 247, 248, 343], 
    [276, 108, 111, 204, 207, 257, 259, 367], 
    [274, 66, 66, 120, 121, nil, 150, nil], 
    [296, 127, 130, 259, 264, 324, 332, nil], 
    [256, 105, 111, 212, 216, 264, nil, nil], 
    [297, 100, 101, 235, 253, nil, nil, nil], 
    [298, 114, 117, 270, 270, nil, nil, nil], 
    [286, 116, 116, 213, nil, nil, nil, nil]] 

誰かが私はこの結果を達成する方法を書くのを手伝っていただけますか?

私が達成しようとしているものの実際の例を見ると役に立つかもしれません。ここでは、スプレッドシートへのリンクです:

https://github.com/SplitTime/OpenSplitTime/blob/master/hardrock2015test.xlsx

各行は、ランナーの努力です。ランナーはコースの最終的な終了時間によってランク付けされます。しかし、終わらない人は、彼らがどれだけそれを作ったのか、彼らが最後の中間地点にそれを作った時によってランクされます。

リンクされたスプレッドシートには表示されませんが、並べ替えには、何らかの理由で記録されなかった時間を表す、右側の時間データのnil値も処理する必要があります。

+1

意味が明確ではありません。要素はその列が変更されていないようです。 **各列**を左から右に並べ替えることはどういう意味ですか? **列**を左から右にソートすることができます(2つ以上)。 – sawa

+1

274,666,666から始まる行がそれ以上ダウンしないのはなぜですか(2番目の要素から最後の要素がnilなので)。 –

+1

あなたの質問は何ですか? – sawa

答えて

2

私はあなたが(nilInfinityとして扱われていると)逆の順序で最後の要素への第二で行をソートしたいを考える

arrays = [[297, 100, 101, 235, 253, nil, nil, nil], 
      [286, 116, 116, 213, nil, nil, nil, nil], 
      [256, 105, 111, 212, 216, 264, nil, nil], 
      [276, 108, 111, 204, 207, 257, 259, 367], 
      [274, 66, 66, 120, 121, nil, 150, nil], 
      [298, 114, 117, 270, 270, nil, nil, nil], 
      [296, 127, 130, 259, 264, 324, 332, nil], 
      [283, 102, 106, 193, 199, 247, 248, 343]] 

arrays.sort_by { |a| a[1..-1].reverse.map { |e| e || Float::INFINITY } } 
#=> [[283, 102, 106, 193, 199, 247, 248, 343], 
# [276, 108, 111, 204, 207, 257, 259, 367], 
# [274, 66, 66, 120, 121, nil, 150, nil], 
# [296, 127, 130, 259, 264, 324, 332, nil], 
# [256, 105, 111, 212, 216, 264, nil, nil], 
# [297, 100, 101, 235, 253, nil, nil, nil], 
# [298, 114, 117, 270, 270, nil, nil, nil], 
# [286, 116, 116, 213, nil, nil, nil, nil]] 

は、少なくとも、これは予想される結果が得られます。

最初の行はキーで構成されているため、Rubyのarray decomposition機能を利用でき、|a| a[1..-1].reverse...の代わりに|_, *vs| vs.reverse...を使用できます。ここで、_は(未使用の)キーを参照し、*vsは残りの要素を収集します。

+0

これはこの場合望ましい結果を生成しますが、私はあらゆる場合に望ましい結果を生成するアルゴリズムを探しています。 – moveson

+0

@movesonあなたは反例を挙げることができますか? – Stefan

+0

私は訂正しました。あなたのコードは完璧かつ即座に動作します。どうもありがとうございます!私はまだ、それが何をしているのかかなり分かりません。あなたは説明できますか? – moveson

関連する問題