2

私はクラスを持っていますTest

class Test 
  attr_accessor :data
  def initialize
    @data = [0, 1, 2, 3]
  end
  def map
    @data.map!{|i| i = yield i }
  end
end

そして私はそれを次のように使おうとします:

a = Test.new

a.map{|i|
  if(i==2)
    i+=1
    break i  #<--- -This line is the focus
  else
    1
  end
}

puts a.data

私が期待する出力はです[1, 1, 3, 3]。代わりに、私は取得し[1, 1, 2, 3]ます。のブロックの最後の反復はmap、変更されたを返しませんi

に置き換えbreak iましたnext i。これは私が期待したとおりに実行され、出力を生成しました[1, 1, 3, 1]

このコード(または、理想的には2番目のコードスニペットで指摘した行)を変更して、出力を取得するにはどうすればよい[1, 1, 3, 3]ですか?言い換えると、どうすればブロックを終了させることができますが、最後の1つの値をに戻すことができmapますか?これを行うためのきちんとした読みやすい方法はありますか(たとえば、ブールフラグを切り替える以外にbreak_now)?

4

3 に答える 3

1

特定の数値セットを計算する方法ではなく、ブロックを離れて計算された最後の値を利用する方法を尋ねていると思います。後者の場合、おそらく賢いワンライナーがあります。

このようなものはどうですか:

class Test
  attr_accessor :data

  def initialize
    @data = [0, 1, 2, 3]
  end

  def modify
    @data.map! {|i| yield i }
  end
end

a = Test.new
a.modify do |i|
  break i if @done
  @done = i == 2
  @done ? (i + 1) : 1
end

puts a.data

追加の考え —#mapは、特定のインターフェイスを持つ Ruby の重要なメソッドです。あなたの例では、 のフィールドを変更してインターフェースに違反していますTest#modifyこのため、代わりに名前を使用しました。

于 2012-12-09T04:27:35.607 に答える
0

一般に、生成された値をその場で変更することで、これを回避できます。たとえば、配列が Fixnum ではなく文字列で構成されている場合:

class Test
  attr_accessor :data

  def initialize
    @data = %w{a b c d}
  end

  def map
    @data.map! { |i| yield i }
  end
end

a = Test.new
a.map do |i|
  if i == 'c'
    i.next!
    break
  else
    'b'
  end
end

p a.data   #=> ["b", "b", "d", "d"]

あなたの例の問題はこれです:

Fixnum オブジェクトには即値があります。これは、それらがパラメーターとして割り当てられたり渡されたりすると、そのオブジェクトへの参照ではなく、実際のオブジェクトが渡されることを意味します。代入は、Fixnum オブジェクトの別名ではありません。与えられた整数値に対して事実上 1 つの Fixnum オブジェクト インスタンスしか存在しません…</p>

Fixnums はその場で変更できないためi += 1、下のブロックの式は上のブロックの値に影響しませんi2それがあなたの例に入る理由ですがd、私の例では。

于 2012-12-09T05:49:09.080 に答える
-1

あなたはこれをしなければなりません:

a.map{ |i| (i % 2 == 0) ? i + 1 : i }

マップ関数を使用する場合、「a」変数は変更しません。「a」変数を変更する場合は、次のようにします。

a.map!{ |i| (i % 2 == 0) ? i + 1 : i }

'i'の新しい値はブロックによって返される値なので、次のようなことはしないでください。

a.map{|i| i = 1 }

あなたがそうするなら:

a.map{|i| i = 1; 5 }

結果は次のようになります。

 [5, 5, 5, 5]
于 2012-12-09T04:23:08.100 に答える