最近用到數(shù)組求和比較頻繁晓猛,了解了一下之前沒怎么用過的inject
數(shù)組求和
Inject最常見的用法
[1, 2, 3, 4, 5].inject(0) { |sum, e| sum + e }
=> 15
或者
(1..5).inject(0) { |sum, e| sum + e }
=> 15
用區(qū)間或者數(shù)組在這里沒有分別砸讳,Ruby會(huì)自動(dòng)轉(zhuǎn)換滤愕。Inject在這里接受一個(gè)方法參數(shù)和一個(gè)block. 對數(shù)組中的每一個(gè)元素芋齿,block都執(zhí)行一次梧却。第一次執(zhí)行block的時(shí)候挡毅,inject接收的方法參數(shù)被作為block的第一個(gè)參數(shù),而block的第二個(gè)參數(shù)則是數(shù)組的第一個(gè)元素仑扑。第二次執(zhí)行block的時(shí)候览爵,情況就有了變化,這也是inject神奇的地方夫壁。這時(shí)候block的第一個(gè)參數(shù)則是block上一次執(zhí)行的返回值(block的最后一個(gè)表達(dá)式)拾枣,第二個(gè)參數(shù)則是數(shù)組的第二個(gè)元素,后面的三次執(zhí)行方式與第二次相同,這樣我們就計(jì)算出了數(shù)組元素之和梅肤。事實(shí)上司蔬,上面的代碼還可以更簡潔一些:
[1, 2, 3, 4, 5].inject { |sum, e| sum + e }
=> 15
這段代碼可以計(jì)算出相同結(jié)果的原因是:inject的方法參數(shù)是可選的,如果不提供的話姨蝴,Ruby默認(rèn)將數(shù)組的第一個(gè)元素作為block第一次執(zhí)行時(shí)候的第一個(gè)參數(shù)俊啼,在這種情況下,block一共需要執(zhí)行4次左医,比傳入默認(rèn)參數(shù)的形式少執(zhí)行一次授帕。
轉(zhuǎn)換數(shù)據(jù)結(jié)構(gòu)
生成Hash:
hash = [[:first_name, 'Shane'], [:last_name, 'Harvie']].inject({}) do |result, element|
result[element.first] = element.last
result
end
當(dāng)然這種用法也有別的形式,并不一定需要用到inject浮梢,比如:
Hash[*[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
2.2 過濾數(shù)組:
arr = [1, 2, 3, 4, 5, 6].inject([]) do |r, e|
r << e.to_s if e % 2 == 0
r
end
當(dāng)然這種用法也有不使用inject的等價(jià)方式:
[1, 2, 3, 4, 5, 6].select { |e| e % 2 == 0 }.collect { |e| e.to_s }
=> ["2", "4", "6"]
(5..10).inject(1) { |product, n| product * n } #=> 151200
longest = %w{ cat sheep bear }.inject do |memo, word| memo.length > word.length ? memo : word end longest #=> "sheep"
求最長的字符串還可以用max方法
a.max { |a, b| a.length <=> b.length } #=> "albatross"
求和還有一個(gè)比較看上去更簡單的方法eval
eval [1,2,3,4].join('+')
Ruby eval方法還可以動(dòng)態(tài)執(zhí)行字符串
a = 1 b="true" c="false" str =" if a==1 then puts '輸出:#跛十' else puts '輸出:#{c}' end " eval(str) => 'true'