2014-04-30 46 views
-1

Ruby的新功能和目前正在学习。有什么办法可以从更大的数组/矩阵中创建2 x 2阵列/矩阵

我不知道我应该使用数组还是矩阵。

我有阵列

[['J','O','I','J','O'], 
['I','J','O','J','O'], 
['I','I','J','I','J']] 

我想找出下面,你可以在图片中看到。

['J', 'O'] 
['I', 'J'] 

enter image description here

我的想法是使用Ruby矩阵,但我不知道我是否可以通过2矩阵原始数组/矩阵划分到小2块,如果它与[J, O], [I, J]匹配。

或者我应该使用数组并循环遍历。

我很欣赏任何输入。

+1

我建议你'需要'矩阵'并使用[Matrix#minor](http://www.ruby-doc.org/stdlib-2.1.0/libdoc/matrix/rdoc/Matrix.html#method -i-minor)方法。 –

+1

@sawa我无法阅读你写的内容。 :( –

+1

我建议你将'['J','O'] ['I','J']'改为'[['J','O'] ['I','J']]' (两行),这样它就是一个有效数组,不需要回复,因为一旦你看到它,我将删除这些注释 –

回答

1

我建议你使用的方法Matrix#minor做到这一点。

代码

require 'matrix' 

def find_in_matrix(arr,sub) 
    sub_nrows = sub.size 
    sub_ncols = sub.first.size 
    rows  = Array[*0..arr.size-sub_nrows] 
    cols  = Array[*0..arr.first.size-sub_ncols] 
    arr_m  = Matrix[*arr] 
    sub_m  = Matrix[*sub] 
    rows.product(cols).select {|i,j| arr_m.minor(i,sub_nrows,j,sub_ncols)==sub_m} 
end 

arr = [['J','O','I','J','O'], 
     ['I','J','O','J','O'], 
     ['I','I','J','I','J']] 

sub = [['J', 'O'], 
     ['I', 'J']] 

find_in_matrix(arr,sub)     #=> [[0, 0], [1, 1], [1, 3]] 
find_in_matrix(arr, [['O'], ['J']])  #=> [[0, 1], [1, 2], [1, 4]] 
find_in_matrix(arr, [['O']])    #=> [[0, 1], [0, 4], [1, 2], [1, 4]] 
find_in_matrix(arr, [['I','J','O']])  #=> [[0, 2], [1, 0]] 
find_in_matrix(arr, [['I','J'],['J','O']]) #=> [] 
find_in_matrix(arr, [[]])     #=> [[0, 0], [0, 1],...,[0, 5]] 
              # [1, 0], [1, 1],...,[1, 5]] 
              # [2, 0], [2, 1],...,[2, 5]] 

说明

对于上面的示例:

sub_nrows = sub.size        #=> 2 
sub_ncols = sub.first.size      #=> 2 
rows  = Array[*0..(arr.size-sub_nrows)]  #=> [0, 1] 
cols  = Array[*0..(arr.first.size-sub_ncols)] #=> [0, 1, 2, 3] 
arr_m  = Matrix[*arr] 
    #=> Matrix[["J", "O", "I", "J", "O"], ["I", "J", "O", "J", "O"], 
    #   ["I", "I", "J", "I", "J"]] 
sub_m  = Matrix[*sub] 
    #=> Matrix[["J", "O"], ["I", "J"]] 

a = rows.product(cols) 
    #=> [[0, 0], [0, 1], [0, 2], [0, 3], [1, 0], [1, 1], [1, 2], [1, 3]] 
a.select {|i,j| arr_m.minor(i,sub_nrows,j,sub_ncols)==sub_m} 
    #=> [[0, 0], [1, 1], [1, 3]] 

考虑aselect通行证的第一个元素到块:[0, 0](即,块变量ij均分配的值为零)。因此,我们计算:

arr_m.minor(i,sub_nrows,j,sub_ncols) #=> arr_m.minor(0,2,0,2) 
    #=> Matrix[["J", "O"], ["I", "J"]] 

由于

arr_m.minor(0,2,0,2) == sub_m 

[0, 0]选择。在另一方面,对于元件的ai => 1, j => 2[1, 2],所以:

arr_m.minor(i,sub_nrows,j,sub_ncols) #=> arr_m.minor(1,2,2,2) 
    #=> Matrix[["O", "J"], ["J", "I"]] 

这不等于sub_m,所以元件[1, 2]未选中。

请注意Matrix#minor有两种形式。我使用了四个参数的表单。另一种形式需要两个范围作为参数。

+0

这看起来比使用数组更清洁! – shin

+0

感谢您的解释。 – shin

+0

谢谢,shin。我通常会提供解释,因为你提到的原因 –

1

您可以定义如下:

def find_in_matrix(matrix, target) 
    (0..matrix.length-target.length).to_a.product(
    (0..matrix.first.length-target.first.length).to_a).select do |x, y| 
    (0...target.length).to_a.product(
     (0...target.first.length).to_a).all? do |test_x, test_y| 
     matrix[x+test_x][y+test_y] == target[test_x][test_y] 
    end 
    end 
end 

matrix = [["J", "O", "I", "J", "O"], 
      ["I", "J", "O", "J", "O"], 
      ["I", "I", "J", "I", "J"]] 

target = [["J", "O"], 
      ["I", "J"]] 

find_in_matrix(matrix, target) 
=> [[0, 0], [1, 1], [1, 3]] 

这种解决方案只是越过的matrixtarget的大小所有子矩阵,并选择等于它的人。

+0

它用这个代码返回[] – shin

+0

@shin - 在'target'中有一个错字输入... –

+0

谢谢,现在它可以工作,我必须研究你的代码 – shin

1

不能直接回答这个问题,而不是一个有效的方式来获得匹配的位置:

matrix = [ 
    %w(J O I J O), 
    %w(I J O J O), 
    %w(I I J I J) 
] 

target = [ 
    %w(J O), 
    %w(I J) 
] 

matrix.each_cons(target.length).each_with_index do |sub, row| 
    sub.map{|a| a.each_cons(target[0].length).to_a}.tap do |sub| 
    head = sub.shift 
    head.zip(*sub).each_with_index do |m, col| 
     if m == target 
     puts "#{row}, #{col}" 
     end 
    end 
    end 
end 
+0

谢谢你,它的工作原理,但代码超出了我的想法 – shin