更改数组元素的周围元素
Changing surrounding elements of an array element
我是初学者,正在做一些练习。我正在尝试操作一个二维数组,如果一个元素是 1,那么周围的非对角线元素应该更改为 1:
[[0,0,0,0],
[0,0,1,0],
[0,0,0,0],
[0,0,0,0]]
应该return
[[0,0,1,0],
[0,1,1,1],
[0,0,1,0],
[0,0,0,0]]
我 运行 遇到了使用嵌套 each_with_index 的问题:在我调整了左右周围的初始更改后,随着方法的迭代,它通过较早的调整进行了拾取并进行了不需要的更改。此外,应该更改 "bottom" 元素的行抛出错误:
a = [[0,0,0,0],
[0,0,1,0],
[0,0,0,0],
[0,0,0,0]
]
a.each_with_index do |m, n| # n == index of main array
m.each_with_index do |x, y| # y == index of subarray
if x == 1
a[n][y+1] = 1 unless (a[n][y+1]).nil? #right
a[n][y-1] = 1 unless (a[n][y-1]).nil? #left
a[n-1][y] = 1 unless (a[n-1][y]).nil? #top
a[n+1][y] = 1 unless (a[n+1][y]).nil? #bottom--currently giving an error
end
end
end
任何关于我如何着手解决这两个方面的建议都会受到欢迎。
为了避免上一步的干扰,您可以(深度)复制数组并将参考数组与修改数组分开,或者在修改数组之前提取所有相关索引。后者更好。此外,使用平面数组比处理嵌套数组容易得多,因此我将 a
与平面数组 b
相互转换,并在 b
.
内工作
b = a.flatten
b
.each_index.select{|i| b[i] == 1}
.each do
|i|
b[i - 1] = 1 if b[i - 1] and i - 1 >= 0
b[i + 1] = 1 if b[i + 1]
b[i - 4] = 1 if b[i - 4] and i - 4 >= 0
b[i + 4] = 1 if b[i + 4]
end
a = b.each_slice(4).to_a
# => [[0, 0, 1, 0], [0, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 0]]
我建议你使用 Matrix class.
require 'matrix'
m = Matrix[*a]
#=> Matrix[[0, 0, 0, 0],
# [0, 0, 1, 0],
# [0, 0, 0, 0],
# [0, 0, 0, 0]]
row, col = m.index(1)
#=> [1, 2]
Matrix.build(m.row_size, m.column_size) { |r,c|
(c-col).abs + (r-row).abs <= 1 ? 1 : 0 }.to_a
#=> [[0, 0, 1, 0],
# [0, 1, 1, 1],
# [0, 0, 1, 0],
# [0, 0, 0, 0]]
它的非矩阵版本(使用方法 Array#index, Fixnum#divmod, Array::new, Enumerable#each_slice 和其他一些方法)如下。
nrows, ncols = a.size, a.first.size
#=> [4, 4]
row, col = a.flatten.index(1).divmod(ncols)
#=> [1, 2]
Array.new(nrows*ncols) do |i|
r, c = i.divmod(ncols)
(c-col).abs + (r-row).abs <= 1 ? 1 : 0
end.each_slice(ncols).to_a
#=> [[0, 0, 1, 0],
# [0, 1, 1, 1],
# [0, 0, 1, 0],
# [0, 0, 0, 0]]
我发现使用 Matrix
class 的方法更容易理解,尽管它可能效率不高。
我是初学者,正在做一些练习。我正在尝试操作一个二维数组,如果一个元素是 1,那么周围的非对角线元素应该更改为 1:
[[0,0,0,0],
[0,0,1,0],
[0,0,0,0],
[0,0,0,0]]
应该return
[[0,0,1,0],
[0,1,1,1],
[0,0,1,0],
[0,0,0,0]]
我 运行 遇到了使用嵌套 each_with_index 的问题:在我调整了左右周围的初始更改后,随着方法的迭代,它通过较早的调整进行了拾取并进行了不需要的更改。此外,应该更改 "bottom" 元素的行抛出错误:
a = [[0,0,0,0],
[0,0,1,0],
[0,0,0,0],
[0,0,0,0]
]
a.each_with_index do |m, n| # n == index of main array
m.each_with_index do |x, y| # y == index of subarray
if x == 1
a[n][y+1] = 1 unless (a[n][y+1]).nil? #right
a[n][y-1] = 1 unless (a[n][y-1]).nil? #left
a[n-1][y] = 1 unless (a[n-1][y]).nil? #top
a[n+1][y] = 1 unless (a[n+1][y]).nil? #bottom--currently giving an error
end
end
end
任何关于我如何着手解决这两个方面的建议都会受到欢迎。
为了避免上一步的干扰,您可以(深度)复制数组并将参考数组与修改数组分开,或者在修改数组之前提取所有相关索引。后者更好。此外,使用平面数组比处理嵌套数组容易得多,因此我将 a
与平面数组 b
相互转换,并在 b
.
b = a.flatten
b
.each_index.select{|i| b[i] == 1}
.each do
|i|
b[i - 1] = 1 if b[i - 1] and i - 1 >= 0
b[i + 1] = 1 if b[i + 1]
b[i - 4] = 1 if b[i - 4] and i - 4 >= 0
b[i + 4] = 1 if b[i + 4]
end
a = b.each_slice(4).to_a
# => [[0, 0, 1, 0], [0, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 0]]
我建议你使用 Matrix class.
require 'matrix'
m = Matrix[*a]
#=> Matrix[[0, 0, 0, 0],
# [0, 0, 1, 0],
# [0, 0, 0, 0],
# [0, 0, 0, 0]]
row, col = m.index(1)
#=> [1, 2]
Matrix.build(m.row_size, m.column_size) { |r,c|
(c-col).abs + (r-row).abs <= 1 ? 1 : 0 }.to_a
#=> [[0, 0, 1, 0],
# [0, 1, 1, 1],
# [0, 0, 1, 0],
# [0, 0, 0, 0]]
它的非矩阵版本(使用方法 Array#index, Fixnum#divmod, Array::new, Enumerable#each_slice 和其他一些方法)如下。
nrows, ncols = a.size, a.first.size
#=> [4, 4]
row, col = a.flatten.index(1).divmod(ncols)
#=> [1, 2]
Array.new(nrows*ncols) do |i|
r, c = i.divmod(ncols)
(c-col).abs + (r-row).abs <= 1 ? 1 : 0
end.each_slice(ncols).to_a
#=> [[0, 0, 1, 0],
# [0, 1, 1, 1],
# [0, 0, 1, 0],
# [0, 0, 0, 0]]
我发现使用 Matrix
class 的方法更容易理解,尽管它可能效率不高。