1

sort_byその方法を理解しようとしています。これが私が実験しているスクリプトです:

def test(x)
  if x[:type] == 1
    # move the hash to the first index of the array
  end
end


values = [{value: "First", type: 0},{value: "Second", type: 1},{value: "1111", type: 0},{value: "2222", type: 1}]
values.sort_by! { |x| test(x) }
puts values

選択したインデックスを移動したいインデックスを明示的に指定するにはどうすればよいですか? タイプ 1 のハッシュをすべて最初の 3 つのインデックスに移動し、それらの順序を変更しないようにします。

4

4 に答える 4

0

#sort または #sort_by を使用する場合、アイテムの移動先のインデックスを宣言することはできません。ただし、順序を指定して、残りは #sort_by に任せることができます。

最初の問題は、sort_by が安定していないことです。等しい項目が任意の順序で発行される可能性があります。安定した並べ替えが必要なので、#stable_sort_by メソッドを持つように Enumerable にモンキー パッチを適用しましょう。

module Enumerable
  def stable_sort_by
    map.each.with_index.sort_by do |e, i|
      [yield(e), i]
    end.map(&:first)
  end
end

これは #sort_by と同じように、ブロックによって返された値に従って並べ替えますが、値が等しい場合はアイテムの順序で並べ替えます。これにより、等しいアイテムの相対的な順序が維持されます。

ここで、新しく定義された #stable_sort_by を使用します。

values.sort_by! do |h|
  if h[:type] == 1
    0
  else
    1
  end
end

これにより、タイプが 1のすべてのアイテムが先頭に移動しますが、それ以外の場合、アイテムの相対的な順序は変更されません。

于 2014-02-11T16:53:21.340 に答える
0

使用したいことを行うにはsort_by(ただし、2 つの要素が同じ値を返す場合、元の順序は保持されませんが、sort_by がどのように機能するかを示しています)

values.sort_by! { |x| x[:type] == 1 ? 0 : 1 }
# =>  [{:value=>"2222", :type=>1}, {:value=>"Second", :type=>1}, 
#      {:value=>"1111", :type=>0}, {:value=>"First", :type=>0}]

sort_byブロックによって返された値に基づいて要素を昇順に並べ替えます。

この場合、配列を反復処理し、各要素を次のブロックに渡します。x

 { |x| x[:type] == 1 ? 0 : 1 }

上記のブロックから返された値は互いに比較され、最終的な順序付き配列の作成に使用されます。

この場合、返される値は0ifx[:type] == 1および1other です。したがって、 を持つすべての要素がx[:type] == 1最初に並べられます。

詳細はsort_by こちら

于 2013-10-09T23:16:54.137 に答える