5

次のRubyコードには、2つのメソッドがd100_in_detectあり、の結果に従ってに含まれる一意の要素(簡単にするための数値)d100_out_detectを返します。Arrayaryd100

def d100
  1 + ( rand 100 )
end

def d100_in_detect( ary )
  choice = [ ]
  100.times do
    choice.push ary.detect { |el| d100 <= el }
  end
  choice.uniq.sort
end

def d100_out_detect( ary )
  choice  = [ ]
  numbers = [ ]

  100.times do
    numbers.push d100
  end

  numbers.each do |i|
    choice.push ary.detect { |el| i <= el }
  end

  choice.uniq.sort
end

ご覧のとおり、2つの方法の違いは、最初の方法ではブロックd100内で呼び出さdetectれ、2番目の方法では100個の乱数がnumbers配列に格納され、で発生するように使用されることd100_in_detectです。

次のように2つのメソッドを呼び出したとしましょう。

ary = [ ]
50.times do |i|
  ary.push i * 5 
end

puts '# IN DETECT #'
print d100_in_detect ary
puts

puts '# OUT DETECT #'
puts d100_out_detect ary
puts

典型的な出力は次のとおりです。

# IN DETECT #
[ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 ]
# OUT DETECT #
[ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100 ]

2つの方法がなぜそのような異なる結果を返すのか理解できません。のブロックd100でメソッドを呼び出すことに何か影響はありますか?detect

4

1 に答える 1

2

右。

私が最初にしたことは、サンプルスクリプトを変更することでした。

def d100_in_detect( ary )
  choice = [ ]
  numbers = []
  100.times do
    var = d100
    numbers << var
    choice.push ary.detect { |el| var <= el }
  end
  puts numbers.inspect
  choice.uniq.sort
end

def d100_out_detect( ary )
  choice  = [ ]
  numbers = [ ]

  100.times do
    numbers.push d100
  end
  puts numbers.inspect

  numbers.each do |i|
    choice.push ary.detect { |el| i <= el }
  end

  choice.uniq.sort
end

ご覧のとおり、私が行ったのは、d100の結果を一時変数に割り当てて、何が起こっているかを確認することだけでした。「バグ」はなくなりました。私の戻り値は突然同じになりました。うーん。

それから、私はまさに何が起こっているのかを思いついた。(2番目の例のように)変数を「キャッシュ」すると、100個の数値の広がりがあることが保証されます。

ブロックを反復処理するとき、ブロック内の番号ごとに、d100を再度実行します。したがって、最初の呼び出しは2番目の呼び出しよりもはるかに多くなります...ただし、呼び出し時にランダムに生成された番号は、その番号よりも大きい必要があります(一方、2でランダムに100を生成する場合は、ある時点で100に達することを保証します)。これにより、スクリプトがより低い数値に大幅に偏ります。

たとえば、次のコマンドを実行します。

@called_count = 0
def d100
  @called_count += 1
  1 + ( rand 100 )
end

def d100_in_detect( ary )
  choice = [ ]
  numbers = []
  100.times do
    choice.push ary.detect { |el| d100 <= el }
  end
  puts @called_count.inspect
  @called_count = 0
  choice.uniq.sort
end

def d100_out_detect( ary )
  choice  = [ ]
  numbers = [ ]

  100.times do
    numbers.push d100
  end
        puts @called_count.inspect
  @called_count = 0

  numbers.each do |i|
    choice.push ary.detect { |el| i <= el }
  end

  choice.uniq.sort
end

私は得る

# IN DETECT #
691
# OUT DETECT #
100
于 2013-01-31T16:28:00.537 に答える