带有随机数的Ruby #detect行为

dav*_*ave 5 ruby random

在下面的Ruby代码中,我有两个方法d100_in_detect,d100_out_detect它们根据结果返回一个Array包含在其中的唯一元素(简称为数字).aryd100

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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,两种方法之间的区别在于,第一种d100是在内部detect块中调用,而在第二种中,100个随机数存储在numbers数组中,然后在发生时使用d100_in_detect.

我们假设我将这两种方法称为如下

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
Run Code Online (Sandbox Code Playgroud)

典型输出如下.

# 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 ]
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚为什么这两种方法会返回不同的结果.d100detect块中调用方法有什么含义吗?

Joe*_*Pym 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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我所做的就是将 d100 的结果分配给一个临时变量以查看发生了什么......然后“错误”就消失了!我的返回值突然变得相同。唔。

然后,我突然意识到发生了什么事。当您“缓存”变量时(如在第二个示例中所做的那样),您保证拥有 100 个数字的分布。

当您迭代该块时,对于块中的每个数字,您将再次执行 d100。因此,第一个比第二个有更多的调用...但是您还要求调用该数字时随机生成的数字大于该数字(而如果您用 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
Run Code Online (Sandbox Code Playgroud)

我明白了

# IN DETECT #
691
# OUT DETECT #
100
Run Code Online (Sandbox Code Playgroud)