2016-09-19 51 views
2

基本上,我試圖用Ruby解決第一個Project Euler問題。 Here是如果你想知道作爲參考的問題。我試圖從頭開始嘗試解決這個問題,但這並沒有太完美,所以我決定採取另一種方式:在網上找到別人的解決方案,分解它,向自己解釋並嘗試看看我是否可以構建我自己的獨特解決方案,如果我能弄清楚他們的代碼究竟在做什麼。根據我的經驗,這只是我學習的最佳方式。下面是我發現的,並決定撕開了解決方案:我對此代碼的工作原理有正確的理解嗎?

puts (1..1000).select{ |n| n % 3 == 0 || n % 5 == 0 }.reduce(:+) 

我發現這個解決方案here。基本上,我想要的不是「告訴我問題的答案」,而是「閱讀我的筆記,並告訴我什麼是對的,什麼是錯的,併爲我逐步分解問題。」再一次,如果這不是一個適當的使用SO,我很抱歉!我不確定要問哪裏,如果這不是我應該問的地方,我會刪除我的問題。 :)下面是我的筆記上的代碼,我如何解釋自己:

  • 它把數1-999(「範圍」)下

  • 然後用「選擇」選擇它。花括號幾乎像css一樣使用,但更類似於Ruby中的「do」和「end」(「do」開始一個命令,「end」結束它)。 「do/end」和大括號之間的區別在於,大括號是可以放入一行而不是需要多行的命令。

  • | | =管道定義了一個「塊」,而「n」代表數字/數字。它是一個包含變量的塊。這意味着| n |要求命令調出選定範圍的數字。
  • 「n%3」尋找3的倍數; == 0查找答案(?)。重複五次。
  • 然後「.reduce(:+)」通過將所有數字相加在一起來縮短命令。

我覺得我對它的理解有點信心,但如果有什麼是關閉(術語,一般概念,等等),我很樂意,如果你讓我知道,解釋!我真的只是試圖學習和把事情分開,向我自己解釋他們通常最能幫助我。

+0

這正是這裏發生了什麼。你理解正確,我無法更好地解釋它。除了你的解釋之外,'.select'就像一個過濾器函數,它過濾了範圍的數組,並且裏面的內容是條件'n%3 == 0 || n%5 == 0'這是選擇可以被3或5整除的所有數字。我的建議是作爲初學者,嘗試以塊格式編寫大部分代碼,以便更好地理解它們在你面前的工作方式將所有東西縮短爲一行。 – lusketeer

+1

'..'從頭到尾*包含*。 '......'*排除*最終值。 –

+0

這兩件事都有幫助!謝謝! –

回答

0

{}大括號的優先級高於

您也可以將{}用於多行。但是do..end不能寫入一行。

對於.select,它返回一個新的數組。

>array = [] 
>array = (1..1000).select{ |n| n % 3 == 0 || n % 5 == 0 } 
>array 

將返回數組編號的那些可通過3或5 1之間被劃分到1000

+4

你可以在單行中使用'do ... end' http://ideone.com/Pe7kMf – Hauleth

+0

所以捲曲基本上,括號比'do ... end'更靈活。並且.select從第一個數組中挑選一些東西,將它們聚集在一起,併爲這些數字提供一個新數組? –

1

在普通的英語語句打印服用1和1000之間的每一個數,其結果是可分通過3或5並返回集合的總和(234168)。

puts只是一個簡單的寫入輸出緩衝區的打印命令(默認爲STDio)。 puts在每個參數後面添加一個換行符。 print沒有。

.select
返回包含所述給定塊 返回一個真值枚舉的所有元素的數組。

所以是在這種情況下,將允許其由3或5

irb(main):005:0> (1..10).select{ |n| n % 3 == 0 || n % 5 == 0 } 
=> [3, 5, 6, 9, 10] 

大括號幾乎都採用類似CSS整除任何價值,但更類似於 「做」和Ruby中的「end」

我不太確定CSS的相似性,因爲CSS只是一種聲明性語言。

大括號和do ... end都是Rubys聲明塊的方式 - 這只是匿名函數。編譯器實際上並不關心,並會讓你用括號編寫多行語句。然而,有一個強大的社區約定,do ... end應該是較長的陳述的首選。

在Javascript中以下劃線庫它看起來像這樣:

console.log( 
    _.filter( 
    _.range(1, 10), function(n){ n % 3 == 0 || n % 5 == 0 } 
) 
); 

reduce(sym) → obj

通過施加一個二進制操作中,由一個塊中指定 或符號結合了枚舉的所有元素命名一個方法或操作符。

因此reduce會將我們得到的數組作爲select的結果並將這些元素添加到一起。 :+實際上是我們所稱的'備忘錄'的方法。

[1,2,3].reduce(:+) 

也可以寫爲:

[1,2,3].reduce { |memo, obj| memo.send(:+, obj) } 
# or 
[1,2,3].reduce { |memo, obj| memo.+(obj) } 

這看起來有點奇怪,但只記得,在Ruby中一切都是對象。 +實際上是FixNum類中的一種方法,而不是其他語言中的關鍵字。

所以1 + 2在Ruby中實際上是語法糖爲1.+(2)

+0

如果我正確理解你,什麼時候使用'do ... end'與何時使用大括號完全是爲了人類的理解,而不是計算機?所以我的代碼不會中斷,如果我使用大括號的多行,它可能不會看起來像「漂亮」。然後減少收集的所有選擇,並記住':+'的記事,總結一切,對吧? –

+1

@SarahAnne:沒錯。 '[1,2,3] .reduce(:+)'相當於'1 + 2 + 3' –

+0

100%正確'[1,2,3] .reduce(&:+)'是相同的作爲你的例子。 '[1,2,3] .reduce(:+)'是符號的特例(較快的一種)。 – Hauleth

0

只是要超明確有關從你的答案該位:

「N%3」尋找3的倍數; == 0查找答案(?)。重複 五。

它不爲5「重複」。在這裏,這個符號「||」代表「邏輯OR」。這意味着,該行:

{ |n| n % 3 == 0 || n % 5 == 0 } 

查找所有數n,使得n是3的倍數或n爲5的倍數。

你可以得到紅寶石邏輯運算符的一個很好的理解,在這裏:

Ruby the Hard Way ex 27

1

它把數1-999( 「範圍」)下

我不知道什麼「把數字放下」應該是這個意思。

puts將給定的對象(即它的參數)寫入standard output這是你的默認終端。在你的例子中,它輸出給定表達式的結果。但要這樣做,表達式必須進行評估。

1..1000創建一個Range,這個對象表示從11000的區間。範圍包含在括號內,因爲1..1000.select將嘗試呼叫1000.select,這會導致錯誤。 (1..1000).select按預期工作。

然後用「.select」選擇它。

select是從Enumerable未來的方法 - 其提供的功能類似ArrayHashRange集合的模塊。 select不會「選擇範圍」,它會根據條件從範圍中選擇元素。把它想象成一個過濾器。

大括號幾乎都採用類似的CSS ...

好,{ ... }被稱爲 「塊」,無論是在CSS和紅寶石。

但在CSS中,這些塊用於將適用於選擇器的多個聲明分組。

在Ruby中,塊參數向該方法發送closure。因此,不是將一個靜態值傳遞給select,而是傳遞一個函數。 select稍後可以調用該函數(即塊)。

...但更類似於Ruby的

「做」和「結束」對於塊,你可以使用do ... end代替{ ... },反之亦然,但你可能必須添加括號或分號來實現相同的結果。

( 「DO」 開始的命令和 「結束」 結尾的話)

,不是命令。

「do/end」和大括號之間的區別在於,大括號表示可以放入一行而不需要多行的命令。

這是一個約定(也有other conventions)。實際的差異是優先級,請參閱block arguments的示例。

| | =管道定義了一個「塊」,而「n」代表數字/數字。它是一個包含變量的塊。

{ ... }定義了一個塊。 | ... |保存傳遞給塊的參數。 n就是這樣的說法。參數的數量由調用塊的方法指定(在本例中爲select),但您可以選擇參數的名稱。

這意味着| n |要求命令調出選定範圍的數字。

該塊是被動的,它不要求任何東西。並沒有「選定範圍」。 select是一種方法。它將範圍內的每個數字傳遞給給定的塊。在該塊內,該編號可以通過n來引用。

即使select不知道元素,它必須調用Range#each才能迭代集合。

「n%3」尋找3的倍數;

n % 3 3返回,即劃分ñ的剩餘部分:

1 % 3 #=> 1  1 divided by 3 = 0, remainder 1 
2 % 3 #=> 2  2 divided by 3 = 0, remainder 2 
3 % 3 #=> 0  3 divided by 3 = 1, remainder 0 
4 % 3 #=> 1  4 divided by 3 = 1, remainder 1 

== 0尋找答案

它(?)比較n % 30的結果。換句話說,n % 3 == 0返回true,如果n可以被3false整除。

重複五次。

還有在它們之間||是一個邏輯

n % 3 == 0 || n % 5 == 0轉換爲「n可被3整除或n可被5整除」

然後「.reduce(:+)」通過將所有數字相加在一起來縮短命令。

首先,select返回一個新的數組。更明確地說,select返回一個新數組,其中包含1..1000的所有元素,塊返回true

reduce然後對所有這些元素應用:+表示的操作。

[1, 2, 3].reduce(:+)相當於1 + 2 + 3