2014-02-08 55 views
2

我想作出這樣的行爲就像一個標準的Ruby哈希在拋出一些額外的訪問方法的類繼承的Ruby類例如,給定:添加一個「每個」一樣的方法,從哈希

class SpecificHash < Hash 
    def initialize 
    (1..20).each do |num| 
     self[num] = "value #{num.to_s}" 
    end 
    end 
end 

我可以得到所有鍵值對的完整列表與標準each電話:

sh = SpecificHash.new 
sh.each { |k,v| puts k } 

我有幾件事情我想這樣做。用一個簡單的例子,我將如何創建一個odd_keys方法的定義,讓我打電話:

sh = SpecificHash.new 
sh.odd_keys { |k,v| puts k } 

,並將它像each方法工作,但只包含鍵/值對其中的關鍵是奇數?

回答

2

加入此方法類應該工作:

def odd 
    return enum_for(:odd) unless block_given? 
    each do |k, v| 
    if k.respond_to?(:odd?) && k.odd? 
     yield k, v 
    end 
    end 
end 

第一行是非常標準的做法,允許,如果塊時,返回一個枚舉不會傳遞給你的方法,就像each一樣。它使諸如:

hash.odd.select { ... } 
+0

是的,這是一個更好的答案! – whatyouhide

+0

我意識到「奇怪?」是一種檢查整數是否奇數的方法。我已經更新了問題,將示例方法重命名爲「odd_keys」以區分這兩者。除非block_given?'返回enum_for(:odd_keys)除非block_given?和'hash.odd是否正確,唯一需要改變的是'def odd'到'def odd_keys'和'return enum_for(:odd) .select {...}'爲'hash.odd_keys.select {...}'? –

+0

是的,這聽起來像你正確地確定了方法名稱出現在我的答案的三個地方,你需要改變所有這些。 –

0

我相信是這樣的:

class SpecificHash < Hash 
    def odd 
    each do |k, v| 
     yield(k, v) if k.odd? 
    end 
    end 
end 
0

我沒有看到爲您的用例定義類的目的。一個枚舉器實例似乎足以滿足您的目的。

sh = (1..20).lazy 
sh.map{|k| [k, "value #{k}"]}.to_h # => ... 
sh.each{|k| puts k} # => ... 
sh.select(&:odd?).each{|k| puts k} # => ... 
+0

我應該更清楚的是,具體的用例僅僅是一個例子。我真正想要的是從基於過濾的散列生成「每個」類型輸出的技術。例如,一個Hash包含一個由ID索引的人員列表,我希望根據每個人的屬性進行方法調用以返回不同的子集。我試圖簡化這個例子,但可能有點過分。 –

+0

不過,最好使用懶惰的枚舉器。您可以使用散列或數組創建惰性枚舉器。它可以讓你添加一系列方法來創建一個「子集」,而不需要創建中間數組/散列,因此它很有效。 – sawa