在运行时,我的代码经常会遇到方法mate
的未定义方法错误。据我所知,Person
在代码的执行过程中某个时候以某种方式滑过裂缝,并设法不分配allele
。
代码(免责声明,不是最佳格式化):
class Allele
attr_accessor :c1, :c2
def initialize(c1, c2)
@c1 = c1
@c2 = c2
end
#formats it to be readable
def to_s
c1.to_s + c2.to_s
end
#given Allele a
def combine(a)
pick = rand(4)
case pick
when 0
Allele.new(c1,a.c1)
when 1
Allele.new(c1,a.c2)
when 2
Allele.new(c2,a.c1)
when 3
Allele.new(c2,a.c2)
end
end
end
class Person
attr_accessor :allele, :male
def initialize(allele,male)
@allele = allele
@male= male
end
#def self.num_people
#@@num_people
#end
def to_s
"Allele:" + allele.to_s + " | Male:" + male.to_s
end
def male
@male
end
def allele
@allele
end
def mate(p)
if rand(2) == 0
Person.new(allele.combine(p.allele),true)
else
Person.new(allele.combine(p.allele),false)
end
end
end
male_array = Array.new
female_array = Array.new
male_child_array = Array.new
female_child_array = Array.new
# EVENLY POPULATE THE ARRAY WITH 5 THAT PHENOTYPICALLY MANIFEST TRAIT, 5 THAT DON'T
# AND 5 GIRLS, 5 GUYS
pheno_dist = rand(5)
#make guys with phenotype
pheno_dist.times { male_array << Person.new(Allele.new(1,rand(2)),true) }
#guys w/o
(5-pheno_dist).times { male_array << Person.new(Allele.new(0,0),true) }
#girls w/ pheno
(5-pheno_dist).times { female_array << Person.new(Allele.new(1,rand(2)),false) }
#girls w/o
pheno_dist.times { female_array << Person.new(Allele.new(0,0),false) }
puts male_array
puts female_array
puts "----------------------"
4.times do
#mates male with females, adding children to children arrays. deletes partners as it iterates
male_array.each do
male_id = rand(male_array.length) #random selection function. adjust as needed
female_id = rand(female_array.length)
rand(8).times do
child = male_array[male_id].mate(female_array[female_id])
if child.male
male_child_array << child
else
female_child_array << child
end
end
male_array.delete_at(male_id)
female_array.delete_at(female_id)
end
#makes males male children, females female children, resets child arrays
male_array = male_child_array
female_array = female_child_array
male_child_array = []
female_child_array = []
puts male_array
puts female_array
puts "----------------------"
end
什么立即出错?
答案 0 :(得分:3)
正如egosys所说,你不应该从你正在迭代的数组中删除。
另一个问题是你的循环开始“4次做”。有时女性数组是空的,所以返回大小为0; rand(0)是随机浮点数&gt; = 0且&lt; 1.在空的female_array上使用它作为数组索引返回nil,然后传递给mate。
但不仅仅是错误。你使用每个人迭代men_array,然后随机挑选一个男性。这允许一些雄性不止一次交配;别人根本没有。同样,有些女性在每次迭代中都会交配并复制不止一次,有些则完全没有。这是你的意图吗?
让我们首先考虑将所有男性和女性保持在同一个阵列中。这将简化事情。但是,既然你确实需要找到所有的男性,有时甚至是所有的女性,我们会为此制定方法:
def males(population)
population.find_all do |person|
person.male?
end
end
def females(population)
population.find_all do |person|
person.female?
end
end
如果男性和女性应该随机配对,那么在生物学上会更准确,但没有人能够多次交配。这很简单:
def random_pairs(males, females)
males.shuffle[0...females.size].zip(females.shuffle)
end
然后简单地再现人口:
def make_children(male, female)
# return an array of children
end
def reproduce(population)
children = []
random_pairs(males(population), females(population)).each do |male, female|
children << make_children(male, female)
end
children
end
具有这样的功能,然后进行4个循环的再现就像这样简单:
people = # ... generate your initial list of people of all sexe.
4.times do
people = reproduce(people)
end
由于没有函数修改传递给它的参数,因此您不会遇到副作用的麻烦。
可以用OO风格完成更多工作,例如使人口成为一流的对象,并将“男性”,“女性”,“随机对”和“再现”等功能移入其中。我将把它作为读者的练习。
答案 1 :(得分:1)
从正在迭代的数组中删除每个都有未定义的行为。通常建议使用Array#delete_if,但我不确定在这种情况下你将如何使用它。