1

#max、#min、#minmax を理解しています。了解です<=>。しかし、これらの関数の 1 つのブロック内でどのように機能するのでしょうか?

つまり、下の 3 行目で何が起こっているのでしょうか。<=> は #min で何をしていますか?

a = %w(albatross dog horse)
a.min                                   #=> "albatross"
a.min { |a, b| a.length <=> b.length }  #=> "dog"

http://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-minの例

数値の配列に対してどのような動作をしますか?

4

2 に答える 2

4

おそらくすでにご覧になっているように、メソッドのドキュメントには次のように記載されています。min

min(n) → array

min(n) {| a,b | block } → array

最小値を持つ enum 内のオブジェクトを返します。最初の形式は、すべてのオブジェクトが を実装することを前提としていますComparable。2 番目は、ブロックを使用して を返しa <=> bます。

これは、最初の形式でminは、配列内のオブジェクトに対してメソッドを呼び出し、<=>その結果を使用してどの要素が最小であるかを判断することを意味します。

2 番目の形式では、min代わりに、比較する両方の要素でブロックを呼び出し、ブロックの戻り値を使用して、どの要素が最小であるかを判断します。基本的に、ブロックを<=>オペレーターの実装であるかのように使用しています。x.min {|a,b| a <=> b }と同等ですx.min

( ) の例では、各要素を比較して並べ替え順序を決定するのではなく、各要素の長さa.min { |a, b| a.length <=> b.length } #=> "dog"を比較してその決定を行うことを意味します。はリスト内の最も短い文字列であるため、それが によって返される値です。、、およびは同様に動作します。"dog"minmaxminmaxsort

min_byより単純なコードで同じ結果を達成するためにその状況で使用することができるので、そこにある例は少し不自然であることに注意してください: a.min_by { |x| x.length }. 並べ替え順序を決定するときに、よりきめ細かい制御が必要minな場合は、ブロックを使用すると適切な場合があります。

数値の配列に対してどのような動作をしますか?

min配列の内容に関係なく、同じように動作します。この場合、{ |a, b| a.length <=> b.length }数値にはメソッドがないため、ブロックを使用しても機能しませんlength。これは数値のより良い例です。最小から最大に並べ替えますが、常に奇数を偶数よりも大きいものとしてカウントします。

[2, 10, 9, 7, 6, 1, 5, 3, 8, 4].sort do |a, b|
  if a.odd? && b.even?
    1
  elsif a.even? && b.odd?
    -1
  else
    a <=> b
  end
end

結果:

[2, 4, 6, 8, 10, 1, 3, 5, 7, 9]

最終的な配列で偶数が奇数の前にソートされることに注意してください。これが に渡したブロックの結果ですsortminmax、およびの動作は同様ですminmax

于 2015-09-04T20:39:16.120 に答える
2

minは 2 つの要素abを配列からブロックに渡し、ブロックはが より小さいか、等しいか、より大きいかに応じて-1、 、0、またはを返すことが期待されます。「宇宙船」演算子は、 、、または値を返します。+1ab<=>-10+1

アルゴリズムは簡単です。比較関数が与えられた場合:

cmp = -> (a, b) { a.length <=> b.length }

最初の要素と 2 番目の要素を比較することから始めます。

cmp.call 'albatros', 'dog'
#=> 1

1'albatros'より大きいことを意味し'dog'ます。より小さい値で続行します。つまり'dog'、それを 3 番目の要素と比較します。

cmp.call 'dog', 'horse'
#=> -1

-1手段'dog'は未満です'horse'。これ以上の要素はありません'dog'。結果も同様です。

このアルゴリズムを Ruby で実装することもできます。

def my_min(ary)
  ary.inject { |min, x| yield(x, min) == -1 ? x : min }
end

ary = %w(albatross dog horse)
my_min(ary) { |a, b| a.length <=> b.length }
#=> "dog"
于 2015-09-04T21:36:44.337 に答える