2012-07-29 58 views
0

我有一个关于识别矩阵中某个给定单元格或某组单元格旁边所有点的问题(请参阅Need a Ruby way to determine the elements of a matrix "touching" another element)。由于没有提出合适的想法,我决定通过强力行动。何时以及如何将代码段转换为红宝石方法

下面的代码成功地做了我想要做的事情。数组tmpl(模板)包含如何从给定坐标(由atlantis提供)到周围8个单元的映射。然后,我通过将atlantis的每个元素与tmpl的所有元素相加来构建一个包含所有“atlantis”海岸线的“水下”土地的阵列sl(海岸线)。

# create method to determine elements contiguous to atlantis 
require 'matrix'    
atlantis = [[2,3],[3,4]] 
tmpl = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]] 

ln = 0 
sl = [] 
while ln < atlantis.length 
    n = 0 
    tsl = [] 
    while n < 8 
    tsl[n] = [atlantis[ln], tmpl[n]].transpose.map { |x| x.reduce(:+) } 
    n = n+ 1 
    end 
    sl = sl + tsl 
    ln = ln + 1 
end 
sl = sl - atlantis 
sl.uniq! 
sl.to_a.each { |r| puts r.inspect } 

但是我有一个问题,我仍然需要2级以上此处显示的循环(许多剩余的一个)(一个继续增加土地亚特兰蒂斯,直到它达到设定规模和另一作出更多岛屿,百慕大群岛,卡塔利娜岛等),而且这已经变得难以阅读和遵循。对面向对象编程的模糊理解表明,通过将这些循环转化为方法可以改进这种冷感。然而,我学会了35年前的基础课程,并努力学习Ruby。所以我的要求是:

  1. 事实上,更好地把它们变成方法?

  2. 如果是这样,任何人都愿意告诉我如何通过改变某种方法来做到这一点?

  3. 当您添加更多关卡并发现您需要在较低方法中更改某些内容时,您会做什么? (例如,搞清楚如何在atlantis只是一个价值创造sl的简单情况后,我不得不回去返工更长的值。)

我问这个问题希望通过这种方式,它变得对其他nubies有用。

顺便说一下,这个位.transpose.map { |x| x.reduce(:+) }我在Stack Overflow上找到了(经过几小时的努力,因为它应该很简单,如果我做不到,我一定会漏掉一些明显的东西。 )使您可以通过添加元素的两个数组元素,我不知道它是如何工作的。)

+0

也许专注于理解你先写的东西。我还会考虑使用更多的空白,以便代码更易于阅读。 – 2012-07-29 23:54:49

+0

让你的代码更像'ruby-like'的一种方法是将你在这里的两个循环替换为更有意义的东西。两者都可以替换为'each'方法(参见http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-each),这将使它更容易理解什么你的代码试图去做。 – 2012-07-30 01:18:02

+0

当你希望不止一次地做同样的操作时,你只需要制定一个方法。如果这个脚本只能有效地调用这个“方法”一次,那么不需要真的改变它。你甚至可以争辩说,这样做会[不成熟的优化](http://c2.com/cgi/wiki?PrematureOptimization)。 – lyonsinbeta 2012-07-30 03:05:40

回答

0

已经是这个变得难以阅读,并按照使其不太难以阅读的

的一种方式接下来是通过使用可读的变量名称和Ruby成语来减少混乱,尝试使代码成为“自我文档”。

你的代码的快速重构给出了这样的:

require 'matrix'    
atlantis = [[2,3],[3,4]] 
template = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]] 

shoreline = [] 
atlantis.each do |atlantum| 
    shoreline += template.inject([]) do |memo, element| 
    memo << [atlantum, element].transpose.map { |x| x.reduce(:+) } 
    memo 
    end 
end 

shoreline = shoreline - atlantis 
shoreline.uniq! 
shoreline.each { |r| puts r.inspect } 

主要处理模块是成功的一半大小,(希望)更具可读性,从这里你可以使用extract method重构进一步,如果把它打扫干净你仍然需要/想要。

+0

谢谢你们。显然更像红宝石。与阿特兰提斯一起使用显然是一条路。我需要学习注入,因为它是陌生的。你是否重写过自己,或者是否使用了特定的重构函数(谢谢您也可以提供)?如果是这样,哪一个? – user918069 2012-07-30 18:08:07

+0

是的,我只是删除了中间变量并替换了'whiles'。 – Pavling 2012-07-30 23:02:20