# 認識Ruby ## 印出hello world 的三種方式 #### 方法一:一行終端機指令: (要注意單引號跟雙引號) $ ruby -e "puts 'hello, world'" #### 方法二:使用 irb。 #### 方法三:寫在某個檔案裡: 例如VScode檔名是 abc.rb,寫完別忘了存檔! 請 Ruby 來執行它: $ ruby abc.rb ## 「print」 vs 「puts」 vs 「p」 #### 印出 Hello, World 字樣 ```ruby= print "Hello, World" ``` #### 印出 Hello, World 字樣,並在結尾加上換⾏ ```ruby= puts "Hello, World" # Hello, World ``` #### 印出 "Hello, World" 字樣(含雙引號),並在結尾加上換⾏ ```ruby= p "Hello, World" # "Hello, World" ``` :::info nil代表不存在 ::: ## 註解 Comment 方式 註解不會被執行 在 Ruby 比較常用單行註解 用途: 說明某段程式碼的用途 暫時把某些程式碼「關起來」 #### 方法一 =begin 這是多⾏註解 這裡的內容不會被執⾏ 這裡的內容不會被執⾏ 這裡的內容不會被執⾏ =end #### 方法二 #這是單⾏註解 #這裡的內容不會被執⾏ #這裡的內容不會被執⾏ #這裡的內容不會被執⾏ ## 變數與常數 a | | = 2 同等 a = a | | 2 如果a的值有設定或是ture就維持原貌,否則給2 --- ### 變數練習 x = 2 , y = 3 將兩者資料對調 #### 方法一、暫存變數 ```ruby= x=2 y=3 a=x x=y y=a ``` #### 方法二、資料總和扣除 ```ruby= x=2 y=3 x= x+y y= x-y x= x-y ``` #### 方法三、 多重指定(ruby專用) ```ruby= x=2 y=3 x,y = y,x ``` :::warning 在Ruby的世界常數是可以被修改的 ::: --- ## 命名慣例 ruby 多用 snale_case --- ## 字串 單引號的字串不會做帶入或翻譯,雙引號的字串會 ### 雙引號 ```ruby= name = "kk" age= 18 puts "hi i am #{name}, i am #{age} years old." ``` result hi i am kk, i am 18 years old. ### 單引號 ```ruby= puts 'hi i am #{name}, i am #{age} years old.' ``` result hi i am #{name}, i am #{age} years old. ### 引號不夠用的狀況 舉例 ```ruby= puts 'i'm #{age} years old.' ``` 解決方法 方法一、加入跳多字元「\」 ```ruby= puts 'i\'m #{age} years old.' ``` 方法二、 用%Q(等同雙引號)或%q(等同單引號) ```ruby= puts %Q(hi i am #{name}, i'm #{age} years old.) puts %q(hi i am #{name}, i'm #{age} years old.) ``` result hi i am kk, i'm 18 years old. hi i am #{name}, i'm #{age} years old. --- ## 數字 (Ruby:數字其實也是物件) ### 整數 ```ruby= puts 3.55.round #轉成整數,四捨五入 puts 3.74.floor #轉成整數,無條件捨去 puts 3.14.ceil #轉成整數,無條件進位 puts 3.14.to_i #轉成整數,無條件捨去 ``` #### 整數除法 (Ruby:整數除以整數會得到整數) ```ruby= puts 10/3 # 會得到3 ``` ### 浮點數 要得到小數的話,只要在整入後面給予小數 ```ruby= puts 10.0/3 puts 10/3.0 pust 10.0/3.0 ``` --- ## 邏輯判斷與流程控制 = => 指定 == => 比對 ```ruby= a=10 b="10" p a==b #false ``` === => 比對or其他事情 ### 判斷 * Ruby中除了**nil**和**false**是假的,其他都是真的 ### if / else ```ruby= weather = "rain" if weather == "rain" puts "stayhome" else puts "GoOut" end ``` #### if 倒裝句 ```ruby= puts "stayhome" if weather == "rain" ``` ### unless unless = if not if = unless not #### 寫法一 ```ruby= if not weather == "rain" #不是rain 就 GoOut puts "GoOut" end ``` #### 寫法二 ```ruby= unless weather == "rain" puts "GoOut" end ``` ### unless 倒裝句 ```ruby= puts "GoOut" if not weather == "rain" puts "GoOut" unless weather == "rain" ``` #### 三元運算子 原本寫法 ```ruby= if age>= 18 status = "adult" else status "notadult" end ``` 三元運算子寫法 ```ruby= status = (age>=18) ? "adult" : "notadult" ``` ### if.. elsif .. else .. * 注意不是 else if 是 elsif ```ruby= weather = "rain" if weather == "rain" puts "HOME" elsif weather == "sunny" puts "OutDoor" else puts "sleep" end ``` ### case .. when .. (Ruby中類似if寫法) 判斷值符合條件 ```ruby= weather = "rain" case weather when "rain" puts "HOME" when "sunny" puts "OutDoor" else puts "sleep" end ``` :::info #### 範圍的shortcut寫法 原本的寫法 ```ruby= age = 10 case age when age >= 0 && age <=3 # 0-3歲 puts "baby" when age >= 4 && age <=10 # 4-10歲 puts "child" when age >= 11 && age <=17 # 11-17歲 puts "teenager" else puts "adult" end ``` shouthand寫法 ( .. => range ) ```ruby= age = 16 case age when 0..3 puts "baby" when 4..10 puts "child" when 11..17 puts "teenager" else puts "adult" end ``` ::: --- ## 迴圈與迭代 :::info 差異性 迴圈: 重複做某一件事(跑5圈操場) 迭代: 每件事都做一次(5座操場各跑1次) ::: ### for 迴圈 (概念有點像迭代) ```ruby= names = ["Amy","John","Tom","Emily"] for name in names # 每一圈在轉的時候都有變數name可以用 puts name end ``` ### while 迴圈 (邪惡分身: until = while not) #### while = until not ```ruby= x = 0 while x < 10 puts x x +=1 #條件記得,不然會無窮迴圈 end ``` #### while not ```ruby= x = 0 until x >= 10 puts x x +=1 end ``` ### loop 迴圈 ```ruby= i = 0 loop do puts i i+=1 break if i > 10 end ``` :::info do .. end(Ruby特有寫法) 或 { } 為block的概念 ::: ### method 迴圈 (Ruby持有) #### .times 做幾次 範例 ```ruby= 5.times do puts "hello, ruby" end ``` #### .upto 向上計數 (從初始值做到設置數值) 範例 ```ruby= 1.upto(10) do |i| puts "counts to #{i}" end ``` #### .downto 向下計數 (從初始值做到設置數值) ```ruby= 10.downto(1) do |i| puts "counts to #{i}" end ``` ### 迭代式迴圈 interation (常用) #### .each ```ruby= names = ["Amy","John","Tom","Emily"] names.each do |name| puts name end ``` 如果想要印出索引值 ```ruby= names = ["Amy","John","Tom","Emily"] names.each.with_index do |name , x| puts "#{x} #{name}" end ``` ## 陣列 ### 建立方式 方式一 用[] ```ruby= list = ["ruby","php","python"] p list #["ruby", "php", "python"] ``` 方式二 用%w,且不用逗號跟雙引號 (%w建立出來的會是字串陣列) ```ruby= list = %w(ruby php python) p list #["ruby", "php", "python"] ``` ### 使用陣列 #### 陣列元素位子 ```ruby= list = %w(ruby php python) p list[2] # "php" ``` ```ruby= list = %w(ruby php python) p list[-1] # "python" ``` :::info 從0開始算,若要從後面開始哪從負值 ::: ### **first** & **last** 取用第一個元素或最後一個元素 ```ruby= list = %w(ruby php python) p list.first #ruby p list.last #python ``` 加括號裡面放入值,可以選擇拿前或後x的數值 ```ruby= list = [1,2,3,4,5,6,7,8,9,10] p list.first(4) #[1, 2, 3, 4] ``` ### 印出陣列長度 .lenght ```ruby= list = %w(ruby php python) puts list.length #3 ``` ### 加入新資料到陣列 #### << ```ruby= list = %w(ruby php python) list << %q(Java) #puts list # ruby php python Java ``` #### 用.push效果一樣 ```ruby= list = %w(ruby php python) list.push('Java') puts list ``` ### map or collect 對集合裡的每個元素**進行運算**,並收集成一個新的**集合**。 ```ruby= list = [1,2,3,4,5] p list.map{|x| x*2} #[2, 4, 6, 8, 10] ``` :::warning 這裡不用%w,印為%w輸出會是內容會是字串 ::: ```ruby= list = [1,2,3,4,5] p list.collect{|x| x*2} #[2, 4, 6, 8, 10] ``` ```ruby= p (1..10).map{|x| x*2} #[2, 4, 6, 8, 10, 12, 14, 16, 18, 20] ``` ### select (filter用途) 從集合裡**挑選符合條件**的元素,並收集成一個新的**集合**。 相反: reject 挑選不符合條件 ```ruby= p (1..10).select {|x| x<5} # [1, 2, 3, 4] ``` ```ruby= p (1..10).reject {|x| x<5} # [5, 6, 7, 8, 9, 10] ``` ### reduce 對集合裡的每個元素**進行運算**,並將所有運算結果歸納成一個**單一結果** 每一圈會將前一次運算完的累加值丟回sum,然後將下一個元素丟入x繼續運算 ```ruby= p (1..10).reduce {|sum, x| sum + x} #55 ``` ### compact 將陣列中的nil拿掉 ```ruby= list=[1,3,4,1,7,nil,7] p list.compact #[1,3,4,1,7,7] ``` ### sort 排序(小到大) ```ruby= list=[1,3,4,1,7,nil,7] p list.compact.sort #[1, 1, 3, 4, 7, 7] ``` ### uniq 將陣列中重複的元素拿掉 ```ruby= list=[1,3,4,1,7,nil,7] p list.compact.sort.uniq #[1, 3, 4, 7] ``` ## 範圍 (1..10) 範圍 1 ~ 10 ('a'..'z') 範圍 a ~ z (1...10) 範圍 1 ~ 9 :::success 口訣: 多一點的少一點,少一點的多一點 ::: * .to_a 會將結果轉為陣列 印出1~10 ```ruby= for i in 1..10 puts i end ``` 練習: 印出 1~100 的單數 ```ruby= p (1..100).select{|x| x%2 ==1} p (1..100).select{|x| x.odd?} #odd:奇數 ?:詢問 odd?:詢問是否為奇數 ``` 印出 1~100 的總和 ```ruby= i = (1..100).to_a p i.reduce{|sum,x| sum+x} p (1..100).sum # sum為單純計算總合用,結果一樣 ``` 印出5個小於100且不重複的亂數 * shuffle 隨機打亂排序, ```ruby= p (1..100).to_a.shuffle.first(5) ``` * simple 從陣列中隨機取樣 ```ruby= p (1..100).to_a.sample(5) ``` --- ## Hash 類似字典的概念,key跟value的組合 :::warning * key跟分號不能有空格 ::: ### 建立方式 ```ruby= a = Hash.new ``` 或用 b= {} 來建立 (name 為 key ,age 為 value) ```ruby= b = {name: 'kk', age: 18} #Ruby 1.9之後的新式寫法 ``` :::info 舊式寫法 ```ruby= b = {:name => 'kk', :age => 18} ``` ::: #### 取用key的值 (對的key拿到對的value) ```ruby= b = {name: 'kk', age: 18} p b[:name] #"kk" ``` #### 印出全部keys跟values的方式 ```ruby= b = { name: 'kk', age: 18} p b.keys #[:name, :age] p b.values #["kk", 18] ``` --- ## 符號 (symbol) 符號不是個變數,他就是一個值 1 是數字物件,"aa"是字串物件,:hello是符號物件 name = "kk" 全域變數name指定為"kk" :name = "kk" 語法錯誤,因為兩個都是值 ```ruby= myname = "Mike" name = :name ``` 字串的內容可以變,但符號(Symbol)不行 ```ruby= name = "abcdefg" name[1] = "x" p name #axcdefg ``` ```ruby= name = :abcdefg name[1] = "x" p name #語法錯誤,符號(Symbol)不能改 ``` 字串的效能比符號差一點 印出 ```ruby= p "hello".object_id 每次都會給新的記憶體位置 p :hello.object_id 每次都會給同一個記憶體位置 ``` :::info object_id 可以印出這個物件在ruby空間的記憶體位置 ::: 冷凍字串 puts "hello".freeze.object_id 固定其記憶體位置 ### 字串轉符號 ```ruby= p "name".to_sym #印出:name p "name".intern #印出:name ``` ### 符號轉字串 ```ruby= p :name.to_s #印出name p :name.id2name #印出name ``` 結論: 字串 vs 符號 不可變,選擇符號or冷凍字串 需要組合需要變化,選擇字串