如何将数组中的 nil 转换为 0 以获得总和?
How do I convert nil to 0 in an array to get the sum?
使用二维数组制作康威生命游戏的一个版本,并且在尝试计算每个单元格 "neighbors" 的总和时,我一直被 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],
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
如果在数组前面包含 "puts",.compact 似乎会产生最多的结果,但我尝试过的 none 选项给我 100%。我试过 reduce(:+)、inject、.to_i、reject(去除 nil 值)等等。
这里缺少什么?
错误:world.rb:35:in block (2 levels) in neighbor_count': undefined method
[]' for nil:NilClass (NoMethodError)
第 35 行是上面的行。compact.sum
零值只是疾病的症状。不要治疗症状,摆脱问题!那是你违反了数组边界。
.each_with_index
枚举从第一个到最后一个的所有索引。因此,最后一个索引上的 idx + 1
将触发这种越界情况。而第一个 idx - 1
将产生意外值而不是错误,这将影响您的计算。祝你调试顺利。 :)
在您的代码中进行一些保护检查,以确保您永远不会越界。
绝对清楚,问题不在于 grid[idx + 1][idx2]
为 nil 并打乱了您的计算。就是grid[idx + 1]
为零!而且,自然地,你不能做 nil[idx2]
。那是错误。
用 1 层边界声明你的网格,那么就不需要放置额外的 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
此代码将简单地生成(有效)邻居。如果没有给出块,第一行 returns 一个枚举数。
代替嵌套upto
loops, you could also utilize repeated_permutation
生成偏移量:
[-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
然而,更重要的是,返回一个枚举器允许您从 Enumerable
链接方法,例如:
def grid
[[1, 2, 1],
[2, 3, 2],
[1, 2, 1]]
end
each_neighbor(1, 1).sum #=> 12
each_neighbor(1, 1).count #=> 8
each_neighbor(0, 0).sum #=> 7
each_neighbor(0, 0).count #=> 3
使用二维数组制作康威生命游戏的一个版本,并且在尝试计算每个单元格 "neighbors" 的总和时,我一直被 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],
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
如果在数组前面包含 "puts",.compact 似乎会产生最多的结果,但我尝试过的 none 选项给我 100%。我试过 reduce(:+)、inject、.to_i、reject(去除 nil 值)等等。
这里缺少什么?
错误:world.rb:35:in block (2 levels) in neighbor_count': undefined method
[]' for nil:NilClass (NoMethodError)
第 35 行是上面的行。compact.sum
零值只是疾病的症状。不要治疗症状,摆脱问题!那是你违反了数组边界。
.each_with_index
枚举从第一个到最后一个的所有索引。因此,最后一个索引上的 idx + 1
将触发这种越界情况。而第一个 idx - 1
将产生意外值而不是错误,这将影响您的计算。祝你调试顺利。 :)
在您的代码中进行一些保护检查,以确保您永远不会越界。
绝对清楚,问题不在于 grid[idx + 1][idx2]
为 nil 并打乱了您的计算。就是grid[idx + 1]
为零!而且,自然地,你不能做 nil[idx2]
。那是错误。
用 1 层边界声明你的网格,那么就不需要放置额外的 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
此代码将简单地生成(有效)邻居。如果没有给出块,第一行 returns 一个枚举数。
代替嵌套upto
loops, you could also utilize repeated_permutation
生成偏移量:
[-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
然而,更重要的是,返回一个枚举器允许您从 Enumerable
链接方法,例如:
def grid
[[1, 2, 1],
[2, 3, 2],
[1, 2, 1]]
end
each_neighbor(1, 1).sum #=> 12
each_neighbor(1, 1).count #=> 8
each_neighbor(0, 0).sum #=> 7
each_neighbor(0, 0).count #=> 3