2012-07-29 57 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