2012-08-16 71 views

回答

8

我會建議用一種新的方法擴展Hash而不是替換has_key?

class Hash 
    def has_rkey?(search) 
    search = Regexp.new(search.to_s) unless search.is_a?(Regexp) 
    !!keys.detect{ |key| key =~ search } 
    end 
end 

這將使用字符串,符號或正則表達式作爲參數。

irb> h = {:test => 1} 
 => {:test=>1}   
irb> h.has_rkey?(:te) 
=> true 
irb> h.has_rkey?("te") 
=> true 
irb> h.has_rkey?(/te/) 
=> true 
irb> h.has_rkey?("foo") 
=> false 
irb> h.has_rkey?(:foo) 
=> false 
irb> h.has_rkey?(/foo/) 
=> false 
+2

請注意,這會將散列數據結構的查找時間複雜度從O(1)更改爲O(n)...,這取決於您的預期用途,可能會完全避免使用散列的好處。 – the911s 2015-08-25 18:13:07

+0

後續心想:如果你有一個大的數據集這樣做,你應該考慮建立某種類型的索引。例如,在一些數據庫,你可以創建一個正則表達式的指數http://dba.stackexchange.com/questions/10694/pattern-matching-with-like-similar-to-or-regular-expressions-in-postgresql – the911s 2015-08-25 18:19:10

2

我不知道這個問題的一個絕對的答案,但如果我寫這個哈克的方法,我會做這個

!!hash.keys.detect{ |k| k.to_s =~ /Your_Regex_here/ } 

這將返回true當任何關鍵字相匹配的正則表達式否則爲false

+1

只是一個提示,只要發現謂詞返回true的元素,'detect'就會停止。這會防止你不必遍歷整個集合,然後檢查,並與'空數組?' – Kyle 2012-08-16 17:03:56

+0

更新我的回答也是如此。 – 2012-08-16 17:14:49

4

如果你只在是/否的答案感興趣,那麼any?可能是一個不錯的選擇:

hash.keys.any? { |key| key.to_s.match(regexp)} 

其中regexp是一個正則表達式。

+1

'any'優於'detect',因爲它根據需要返回布爾值。注意:您有一個錯字:鍵=>鍵 – 2015-09-04 14:51:17

+0

感謝,錯字是固定的,是的,這樣做的主要原因 - 晚 - 答案是提供一種方法,你不必''!!拿到' boolean'。 – qqbenq 2015-09-07 08:43:41

+0

'hash.keys.find {...}'將返回密鑰名稱,如果需要 – 2016-09-13 15:19:16

3

我認爲使用any?是一個很好的解決方案,如qqbenq所述,但我更願意將它與grep一起使用,因爲它更簡潔。 hash.keys.grep(/regexp/).any?