在二维数组中搜索零并制作相应的行和列 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的主要内容,如果未能解决你的问题,请参考以下文章

java基础_二维数组的行和列

在二维数组中的行和列处查找最大值

二维数组a[11][11]数组元素个数

二维数组的 每行的元素个数必须一样吗?

如何在 C++ 中获取二维动态数组的行数和列数

二维数组3:搜索二维矩阵