1. 快速擷取Regex的匹配值
通常我們使用Regex,都是先match,然後再取結果,但是這樣有時候會拋異常,看下面例子:
複製代碼 代碼如下:
email = "Fred Bloggs "
email.match(//)[1] # => "fred@bloggs.com"
email[//, 1] # => "fred@bloggs.com"
email.match(/(x)/)[1] # => NoMethodError [:(]
email[/(x)/, 1] # => nil
email[/([bcd]).*?([fgh])/, 2] # => "g"
上面例子中還有一種更簡單的方法,就是使用 String#[]方法,可以直接匹配Regex,更簡潔,雖然看起來使用了魔鬼數字。
當然你可以省略掉那個魔鬼數字,如果僅匹配一次的話:
複製代碼 代碼如下:
x = 'this is a test'
x[/[aeiou].+?[aeiou]/] # => 'is i'
這個例子中,我們匹配規則“先匹配一個母音,然後一個輔音,再接著一個母音”。
2. Array#join!的快捷實現
我們知道Array的*操作,是將數組裡面的元素成倍的增加:
複製代碼 代碼如下:
[1, 2, 3] * 3 == [1, 2, 3, 1, 2, 3, 1, 2, 3]
但是當乘因子不是數字是字串會出現什麼效果?
複製代碼 代碼如下:
%w{this is a test} * ", " # => "this, is, a, test"
h = { :name => "Fred", :age => 77 }
h.map { |i| i * "=" } * "n" # => "age=77nname=Fred"
對了,這就是join!的效果。因此可以用這種方式來快捷地實現join!操作。
3. 快速格式化十進位數字
格式化浮點數字的精度顯示通常使用sprintf這個函數,可是有一種更快捷的方式,使用字串。
複製代碼 代碼如下:
money = 9.5
"%.2f" % money # => "9.50"
4. 快速解析字串
在技巧3中我們看到了數位格式化,這裡就說一下字串格式的捷徑。
複製代碼 代碼如下:
"[%s]" % "same old drag" # => "[same old drag]"
這裡的意思是將”same old drag”顯示到[]中。
我們再看一下具體的格式化方法:
複製代碼 代碼如下:
x = %w{p hello p}
"%s" % x # => "
hello
”
5. 遞迴刪除檔案和目錄
FileUtils提供了這種方法:
複製代碼 代碼如下:
require 'fileutils'
FileUtils.rm_r 'somedir'
還有一個方法是FileUtils.rm_rf,與linux上的 rm -rf 對應。
6. 快速窮舉可枚舉對象
使用*操作可以快速的窮舉出可枚舉對象中的所有元素,像Array,Hash這種對象。
複製代碼 代碼如下:
a = %w{a b}
b = %w{c d}
[a + b] # => [["a", "b", "c", "d"]]
[*a + b] # => ["a", "b", "c", "d"]
這裡*操作符的優先順序低於+操作符。
複製代碼 代碼如下:
a = { :name => "Fred", :age => 93 }
[a] # => [{:name => "Fred", :age =>93}]
[*a] # => [[:name, "Fred"], [:age, 93]]
a = %w{a b c d e f g h}
b = [0, 5, 6]
a.values_at(*b).inspect # => ["a", "f", "g"]
7. 消除臨時變數
我們有時候需要寫一個臨時變數如一個臨時的Array,有一種方式可以不用單獨定義臨時變數:
複製代碼 代碼如下:
(z ||= []) << 'test'
當然這不是一種很好的編程習慣,建議不要大量在代碼中使用。
8. 使用非字串或非Symbol對象作為Hash的Key
或許你從來沒有嘗試過使用非String或非Symbol對象作為Hash的Key,但是確實是可以的,有時候還蠻有用。
複製代碼 代碼如下:
does = is = { true => 'Yes', false => 'No' }
does[10 == 50] # => "No"
is[10 > 5] # => "Yes"
9. 使用and或or將多個操作組合到一行
這個技巧很多熟練的Ruby程式員都會使用,用來替代if和unless這種短行代碼。
複製代碼 代碼如下:
queue = []
%w{hello x world}.each do |word|
queue << word and puts "Added to queue" unless word.length < 2
end
puts queue.inspect
# Output:
# Added to queue
# Added to queue
# ["hello", "world"]
但是注意,這種方式,若and左邊運算式“queue << word”返回nil則“puts "Added to queue"”不會被執行,要慎用。不是Geek建議不要用。
10. 判斷當前Ruby解析器是否在執行自己的指令碼
有時候你可能需要判斷當前的運行環境是否在自己的Ruby指令檔中,那麼可以使用:
複製代碼 代碼如下:
if __FILE__ == $0
# Do something.. run tests, call a method, etc. We're direct.
end
11. 快速地批量給變數賦值
最常用的多個變數賦值方法是:
複製代碼 代碼如下:
a, b, c, d = 1, 2, 3, 4
在函數中可以批量賦值,通過傳*的參數:
複製代碼 代碼如下:
def my_method(*args)
a, b, c, d = args
end
還可以大量設定成員變數:
複製代碼 代碼如下:
def initialize(args)
args.keys.each { |name| instance_variable_set "@" + name.to_s, args[name] }
end
12. 使用range替代複雜的數字大小比較
如果要比較if x > 1000 && x < 2000 ,可以使用如下方式替代:
複製代碼 代碼如下:
year = 1972
puts case year
when 1970..1979: "Seventies"
when 1980..1989: "Eighties"
when 1990..1999: "Nineties"
end
13. 使用枚舉操作替換重複代碼
寫代碼最忌諱“重複”,在Ruby中有時候會require很多檔案,可以使用下面的方式省去重複的require:
複製代碼 代碼如下:
%w{rubygems daemons eventmachine}.each { |x| require x }
14. 三元操作
Ruby和其他語言一樣,有三元操作:
複製代碼 代碼如下:
puts x == 10 ? "x is ten" : "x is not ten"
# Or.. an assignment based on the results of a ternary operation:
LOG.sev_threshold = ENVIRONMENT == :development ? Logger::DEBUG : Logger::INFO
15. 嵌套的三元操作
複製代碼 代碼如下:
qty = 1
qty == 0 ? 'none' : qty == 1 ? 'one' : 'many'
# Just to illustrate, in case of confusion:
(qty == 0 ? 'none' : (qty == 1 ? 'one' : 'many'))
16. 幾種返回true,false的實現
最普通的是:
複製代碼 代碼如下:
def is_odd(x)
# Wayyyy too long..
if x % 2 == 0
return false
else
return true
end
end
可以簡潔一點是:
複製代碼 代碼如下:
def is_odd(x)
x % 2 == 0 ? false : true
end
還可以更簡潔:
複製代碼 代碼如下:
def is_odd(x)
# Use the logical results provided to you by Ruby already..
x % 2 != 0
end
當然,有時候你擔心返回的nil(ruby中的判定規則是nil為false,其他都為true),那麼可以顯示轉換:
複製代碼 代碼如下:
class String
def contains_digits
self[/d/] ? true : false
end
end
17. 查看異常堆棧
複製代碼 代碼如下:
def do_division_by_zero; 5 / 0; end
begin
do_division_by_zero
rescue => exception
puts exception.backtrace
end
18. 將一個對象轉換為數組
*操作符可以將一個對象轉換為數組對象
複製代碼 代碼如下:
1.9.3p125 :005 > items = 123456
=> 123456
1.9.3p125 :006 > [*items]
=> [123456]
1.9.3p125 :007 > [*items].each do | i | puts i end
123456
=> [123456]
19. 沒有begin的rescue塊
Ruby中捕獲異常的代碼是begin...rescue...:
複製代碼 代碼如下:
def x
begin
# ...
rescue
# ...
end
end
但是rescue可以沒有begin:
複製代碼 代碼如下:
def x
# ...
rescue
# ...
end
20. 塊注釋
C和Java中的塊代碼注釋是/**/,ruby中也有類似的塊注釋:
複製代碼 代碼如下:
puts "x"
=begin
this is a block comment
You can put anything you like here!
puts "y"
=end
puts "z"
21. 拋出異常
Java中拋異常是使用throw,ruby中更靈活,可以在一行代碼中直接拋異常而不中斷當前調用棧:
複製代碼 代碼如下:
h = { :age => 10 }
h[:name].downcase # ERROR
h[:name].downcase rescue "No name" # => "No name"