在二维数组中搜索零并制作相应的行和列 0
Posted
技术标签:
【中文标题】在二维数组中搜索零并制作相应的行和列 0【英文标题】:Search for zero in 2D array and make a corresponding row and col 0 【发布时间】:2015-08-26 00:49:09 【问题描述】:这是我的代码,它有效,但它太大了。我想重构它。
req_row = -1
req_col = -1
a.each_with_index do |row, index|
row.each_with_index do |col, i|
if col == 0
req_row = index
req_col = i
break
end
end
end
if req_col > -1 and req_row > -1
a.each_with_index do |row,index|
row.each_with_index do |col, i|
print (req_row == index or i == req_col) ? 0 : col
print " "
end
puts "\r"
end
end
输入:二维数组
1 2 3 4
5 6 7 8
9 10 0 11
12 13 14 15
需要的输出:
1 2 0 4
5 6 0 8
0 0 0 0
12 13 0 15
【问题讨论】:
这会减少你的代码row.index(0)
值得注意的是,您的程序只显示零,实际上并没有改变数组。
@tadman 你能帮忙怎么做吗
我假设答案应该能够处理包含多个零的数组,对吗?您的代码无法处理这种情况。
我想提供一些关于提出问题的建议: 1) 总是从用文字解释你想要做什么开始。在这里,您可能会说,“如果二维数组包含零,我想将相关行和列中的所有元素都转换为零”。 (这不是很精确,因为数组没有行和列,但它得到了整个想法。) 2)添加一个具有预期结果的示例。您已经这样做了,但是该示例应该引用有效的 Ruby 对象。在某种程度上,这是为了让读者可以剪切和粘贴。另外,给输入值命名,以便答案可以引用它们(续..)
【参考方案1】:
我很惊讶Matrix 类没有被更多使用:
a = [[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 0, 11],
[12, 13, 14, 15]]
require 'matrix'
m = Matrix.rows(a)
#=> Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 0, 11], [12, 13, 14, 15]]
r, c = m.index(0)
#=> [2, 2]
Matrix.build(m.row_count, m.column_count) |i,j| (i==r || j==c) ? 0 : m[i,j].to_a
#=> [[ 1, 2, 0, 4],
# [ 5, 6, 0, 8],
# [ 0, 0, 0, 0],
# [12, 13, 0, 15]]
注意Matrix
对象是不可变的。要更改单个元素,您必须创建一个新矩阵。
如果您希望对矩阵中的每个零都进行此操作,则需要稍作修改:
a = [[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 0, 11],
[ 0, 13, 14, 15]]
require 'set'
m = Matrix.rows(a)
#=> Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 0, 11], [0, 13, 14, 15]]
zero_rows = Set.new
zero_columns = Set.new
m.each_with_index |e,i,j| (zero_rows << i; zero_columns << j) if e.zero?
zero_rows
#=> #<Set: 2, 3>
zero_columns
#=> #<Set: 2, 0>
Matrix.build(m.row_count, m.column_count) do |i,j|
(zero_rows.include?(i) || zero_columns.include?(j)) ? 0 : m[i,j]
end.to_a
#=> [[0, 2, 0, 4],
# [0, 6, 0, 8],
# [0, 0, 0, 0],
# [0, 0, 0, 0]]
【讨论】:
我成为 Ruby 专家已经有一段时间了,但从未接触过 Matrix 类,非常酷。【参考方案2】:试试这个代码:
req_row = req_col = -1
a.each_with_index do |row, index|
req_col = row.index(0) # searching index having value 0.
if req_col
req_row = index
break
end
end
a.each_with_index do |row,index|
row.each_with_index do |col, i|
print ((req_row == index or i == req_col) ? 0 : col).to_s + " "
end
puts "\r"
end
【讨论】:
这段代码运行良好,但我们可以减少一个循环来搜索“0”【参考方案3】:根据您的问题的标题,这里的解决方案是搜索零值 (fixate
) 的位置,然后实际上将相应的行和列归零(clear
,更符合您的问题的内容) :
def fixate matrix, search=0, replace=0
rcs = []
matrix.each_with_index do |row,r|
row.each_with_index do |col,c|
rcs << [ r, c ] if col == search
end
end
rcs.each do |(row, col)|
clear matrix, row, col, replace
end
matrix
end
def clear matrix, row, col, val=0
matrix[row].map! |_| val # Clear rows
matrix.each |r| r[col] = val # Clear columns
matrix
end
快速测试:
fixate [ # [
[ 1, 2, 3, 4 ], # [ 1, 2, 0, 4 ],
[ 5, 6, 7, 8 ], # [ 5, 6, 0, 8 ],
[ 9, 10, 0, 11 ], # [ 0, 0, 0, 0 ],
[ 12, 13, 14, 15 ] # [ 12, 13, 0, 15 ]
] # ]
【讨论】:
Loos 很好,但是return
语句对于 Ruby 标准来说是相当沉重的。 if 在方法的末尾是隐含的。不知道为什么在 matrix.each |r| r[col] = val
会做同样的工作时使用 matrix.size.times
。
考虑到您的建议。
现在看起来很瘦很刻薄。【参考方案4】:
这是我想出的:
zero_rows=[]
a.map do |col|
col.each_with_index do |el, index|
zero_rows.push(index) if el==0
end
col.fill(0) if col.include?(0)
end
a.map|col| zero_rows.each|index| col[index]=0
首先,使用map
遍历列,如果它们至少包含一个0,则使用fill
以零。但是,在这样做的同时,将包含0 的索引添加到zero_rows
数组中。
然后,再次遍历数组,并将与zero_rows
中的索引匹配的每一列的索引设置为0。
您可能知道map
方法为collect
。他们做同样的事情。
旁注:
如果一个数组包含多个零,则此代码会将每个适用的列归零。 OP 的示例和此处的其他一些答案只会将找到 0 的第一列归零。如果这是您所期望的行为,请查看@Doguita 的回答。
【讨论】:
【参考方案5】:我不知道这段代码是否比其他答案更好。我稍后会测试它:
ary = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 0, 11], [12, 13, 14, 15]]
col = nil
row = ary.index |a| col = a.index(0)
ary.each_with_index |a, i| i == row ? a.fill(0) : a[col] = 0 if col
p ary
# => [[1, 2, 0, 4], [5, 6, 0, 8], [0, 0, 0, 0], [12, 13, 0, 15]]
Obs:这个答案假设数组中只有一个 0 可以搜索
【讨论】:
如果数组包含多个 0,这将不起作用 @LukeP 我知道,但它适合 OP 示例。您确定需要搜索多个 0 吗? 我只能这样假设。一个好的答案也应该更健壮,以便对未来的读者更有帮助。不过,我会在 cmets 中要求澄清。 同时,如果您编辑答案,我只能撤消我的反对票。 (所以锁定了我的投票)以上是关于在二维数组中搜索零并制作相应的行和列 0的主要内容,如果未能解决你的问题,请参考以下文章