2013-01-31 22 views
5

W następnym kodem Ruby, że istnieją dwa sposoby d100_in_detect i d100_out_detect które zwracają Array niepowtarzalnych elementów (liczby dla uproszczenia) zawartych w ary zgodnie z wynikiem d100.Ruby zachowanie #detect losowych liczb

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 

Jak widać różnicę między tymi dwoma metodami jest to, że w pierwszym d100 nazywa się wewnątrz bloku detect „s, natomiast w drugim 100 liczb losowych są przechowywane w numbers Array i następnie są wykorzystywane jak to się dzieje w d100_in_detect.

Załóżmy wzywam dwie metody następująco

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 

Typowa wyjściowa jest następująca.

# 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 ] 

Nie mogę zrozumieć, dlaczego te dwie metody zwracają tak różne wyniki. Czy istnieje jakiś implikacja w wywołaniu metody d100 w bloku ?

Odpowiedz

2

Dobrze.

Pierwszą rzeczą, jaką zrobiłem było zmodyfikować przykładowy skrypt:

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 

Jak widać, wszystko zrobiłem było przypisać wynik d100 do zmiennej tymczasowej, aby zobaczyć, co się dzieje .... i "błąd" odszedł! Moje wartości zwracane były nagle identyczne. Hmm.

Potem przyszło mi do głowy, co się dzieje. Kiedy "buforujesz" zmienną (tak jak w drugim przykładzie), gwarantujesz, że masz rozpiętość 100 numerów.

Po przejściu przez blok, dla każdej liczby w bloku, ponownie wykonasz d100. Dlatego też pierwsza z nich ma znacznie więcej wywołań niż druga ... ale ty również potrzebujesz losowo wygenerowanej liczby w czasie, gdy ta liczba została wywołana, aby była większa od liczby (podczas gdy, jeśli losowo wygenerujesz 100 za pomocą 2, możesz zagwarantować, że uderzy w 100 w pewnym momencie). To drastyczne nastawienie jest twoim scenariuszem na niższe liczby!

Dla przykładu, uruchom:

@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 

uzyskać

# IN DETECT # 
691 
# OUT DETECT # 
100 
+0

dzięki za numer _each w bloku, należy wykonać again_ D100. – dave

+0

Tak, to naprawdę kluczowa część. Resztę załączyłem, ponieważ musiałem biegać i bawić się scenariuszem, aby zrozumieć, co się dzieje. Dziękuję za udzielenie tak szczegółowego pytania! –