Arrays 如何将数组中的nil转换为0以获得和?
在康威的《生活游戏》中,我使用2d数组进行工作,当我试图计算每个细胞的“邻居”之和时,我总是被nil值挡住Arrays 如何将数组中的nil转换为0以获得和?,arrays,ruby,sum,conways-game-of-life,Arrays,Ruby,Sum,Conways Game Of Life,在康威的《生活游戏》中,我使用2d数组进行工作,当我试图计算每个细胞的“邻居”之和时,我总是被nil值挡住 def neighbor_count grid.each_with_index do |row, idx| row.each_with_index do |column, idx2| [grid[idx - 1][idx2 - 1], grid[idx - 1][idx2], grid[idx - 1][idx2 + 1],
def neighbor_count
grid.each_with_index do |row, idx|
row.each_with_index do |column, idx2|
[grid[idx - 1][idx2 - 1], grid[idx - 1][idx2], grid[idx - 1][idx2 + 1],
grid[idx][idx2 - 1], grid[idx][idx2], grid[idx][idx2 + 1],
grid[idx + 1][idx2 - 1], grid[idx + 1][idx2], grid[idx + 1][idx2 + 1]
].compact.sum
end
end
end
.compact似乎在数组前面包含“puts”时效果最好,但我尝试过的选项中没有一个是100%。我尝试过reduce(:+)、inject、.to_I、reject(去掉nil值)等等
这里少了什么
错误:world.rb:35:in块(2级)中的邻居计数:nil:NilClass(NoMethodError)的未定义方法
第35行是上面的那行。)compact.sumnil值只是疾病的症状。不要治疗症状,解决问题!也就是说您违反了数组边界
。每个带有索引的索引都会枚举从第一个到最后一个的所有索引。因此,最后一个索引上的idx+1
将触发这种越界情况。和idx-1
在第一个上会产生一个意外的值,而不是一个错误,这将影响您的计算。祝你好运。:)
在你的代码中加入一些守卫检查,以确保你永远不会越界
需要明确的是,问题不在于grid[idx+1][idx2]
为零并且会打乱您的计算。这是因为网格[idx+1]
为零!而且,很自然,您不能执行nil[idx2]
。这就是错误所在。零值只是疾病的症状。不要治疗症状,解决问题!也就是说您违反了数组边界
。每个带有索引的索引都会枚举从第一个到最后一个的所有索引。因此,最后一个索引上的idx+1
将触发这种越界情况。和idx-1
在第一个上会产生一个意外的值,而不是一个错误,这将影响您的计算。祝你好运。:)
在你的代码中加入一些守卫检查,以确保你永远不会越界
需要明确的是,问题不在于grid[idx+1][idx2]
为零并且会打乱您的计算。这是因为网格[idx+1]
为零!而且,很自然,您不能执行nil[idx2]
。这就是错误。声明您的网格有一层边界,那么就不需要添加额外的if/else子句,也可以使用方向向量访问循环中的邻居
#let say you want to delare 4x4 grid, declare grid of (row+2, col+2)
row, col, default_value = 4, 4, 0
grid = Array.new(row+2){Array.new(col+2,default_value)}
# store direction vectors dx and dy
dx = [-1, -1, -1, 0, 1, 1, 1, 0, 0]
dy = [-1, 0, 1, 1, 1, 0, -1, -1, 0]
(1..row).each do |i|
(1..col).each do |j|
puts (0..8).reduce(0) { |sum, k| sum + grid[i + dx[k]][j + dy[k]]}
end
用一层边界声明你的网格,这样就不需要额外的if/else子句,也可以使用方向向量访问循环中的邻居
#let say you want to delare 4x4 grid, declare grid of (row+2, col+2)
row, col, default_value = 4, 4, 0
grid = Array.new(row+2){Array.new(col+2,default_value)}
# store direction vectors dx and dy
dx = [-1, -1, -1, 0, 1, 1, 1, 0, 0]
dy = [-1, 0, 1, 1, 1, 0, -1, -1, 0]
(1..row).each do |i|
(1..col).each do |j|
puts (0..8).reduce(0) { |sum, k| sum + grid[i + dx[k]][j + dy[k]]}
end
您可以将邻居的枚举移动到单独的方法中:
def each_neighbor(x, y)
raise IndexError unless within_bounds?(x, y)
return enum_for(:each_neighbor, x, y) unless block_given?
(y - 1).upto(y + 1) do |j|
(x - 1).upto(x + 1) do |i|
next unless within_bounds?(i, j) # skip out of bounds cells
next if i == x && j == y # skip middle cell
yield grid[i][j]
end
end
end
给定坐标x
和y
此代码将简单地生成(有效)邻居。如果没有给出块,第一行返回一个枚举数
除了嵌套循环,您还可以利用来生成偏移:
[-1, 0, 1].repeated_permutation(2) do |dx, dy|
next unless within_bounds?(x + dx, y + dy)
next if dx.zero? && dy.zero? # skip middle cell
yield grid[x + dx][y + dy]
end
但是,更重要的是,返回枚举数允许您从以下位置链接方法:
您可以将邻居的枚举移动到单独的方法中:
def each_neighbor(x, y)
raise IndexError unless within_bounds?(x, y)
return enum_for(:each_neighbor, x, y) unless block_given?
(y - 1).upto(y + 1) do |j|
(x - 1).upto(x + 1) do |i|
next unless within_bounds?(i, j) # skip out of bounds cells
next if i == x && j == y # skip middle cell
yield grid[i][j]
end
end
end
给定坐标x
和y
此代码将简单地生成(有效)邻居。如果没有给出块,第一行返回一个枚举数
除了嵌套循环,您还可以利用来生成偏移:
[-1, 0, 1].repeated_permutation(2) do |dx, dy|
next unless within_bounds?(x + dx, y + dy)
next if dx.zero? && dy.zero? # skip middle cell
yield grid[x + dx][y + dy]
end
但是,更重要的是,返回枚举数允许您从以下位置链接方法:
谢谢我得到了,并期望生成零值,因为它是。关于如何有效地排除任何超出边界的坐标,有什么建议吗?@JeremyFlagan:是的,一些if可以很好地完成这项工作。@JeremyFlagan:这是我多年前编写的一个生活游戏。因此,无需对代码进行判断:)您可以通过使用散列而不是数组来避免边界检查<代码>网格[1][2]
将变成网格[[1,2]]
。您甚至可以给散列一个默认值0
@Stefan:或将单元格访问封装在一个方法中(该方法将包含适当的保护和默认值):get\u cell(1,2)
谢谢。我得到了,并期望生成零值,因为它是。关于如何有效地排除任何超出边界的坐标,有什么建议吗?@JeremyFlagan:是的,一些if可以很好地完成这项工作。@JeremyFlagan:这是我多年前编写的一个生活游戏。因此,无需对代码进行判断:)您可以通过使用散列而不是数组来避免边界检查<代码>网格[1][2]
将变成网格[[1,2]]
。你甚至可以给散列一个默认值0
@Stefan:或者将单元格访问封装在一个方法中(该方法将包含适当的保护和默认值):get_cell(1,2)
如果要使用填充,则必须在字段的所有边添加它,不?@SergioTulentsev感谢先生指出这一点,很好的捕获,编辑了答案。如果要使用填充,则必须在字段的各个面添加填充,否?@SergioTulentsev感谢先生指出这一点,好的,编辑了答案。