ruby迭代哈希

时间:2013-07-14 08:01:29

标签: ruby algorithm trie

我有哈希哈希。这个哈希有一个字典。我需要在其中找到具有相同根的所有匹配项。例如,我有:

#<Trie:0x00000001bf9a40 @root={
  "m"=>{"a"=>{"x"=>{
    :end=>true,
    "i"=>{"m"=>{
      :end=>true,
      "i"=>{"m"=>{"l"=>{"i"=>{"a"=>{"n"=>{:end=>true}}}}}}
    }},
    "w"=>{"e"=>{"l"=>{"l"=>{:end=>true}}}}
  }}}
}>

和字"max""maxim""maximilian""maxwell"。如何通过root获取此哈希中的所有单词?例如

t = Trie.new
t.add( .....# now we added words
t.find('max')
#result all words which begins from 'max'
t.find('maxim')
#result all words which begins from 'maxim' => maxim, maximilian

3 个答案:

答案 0 :(得分:1)

看起来我的find方法与@ sawa非常相似。 (我相信@sawa是第一次教我使用inject&:[]这样的情况的人,所以这很合适。)

假设:

class Trie
  def initialize(root)
    @root = root # Just a shortcut to use your data and focus on your question
  end

  # Recurses through Hash `h` to find all words starting with `s`
  def words(h, s, a=[])
    h.each do |k, v|
      if k == :end
        a << s
      else
        words(v, s+k, a)
      end
    end

    a
  end

  private :words

  def find(start)
    words(start.chars.inject(@root, &:[]), start) rescue []
  end
end

t = Trie.new({"m"=>{"a"=>{"x"=>{:end=>true,
                              "i"=>{"m"=>{:end=>true,
                                         "i"=>{"m"=>{"l"=>{"i"=>{"a"=>{"n"=>{:end=>true}}}}}}}},
                              "w"=>{"e"=>{"l"=>{"l"=>{:end=>true}}}}}}}})

你可以这样做:

t.find('max')
# => ["max", "maxim", "maximimlian", "maxwell"]
t.find('maxi')
# => ["maxim", "maximimlian"]
t.find('maximi')
# => ["maximimlian"]
t.find('maxw')
# => ["maxwell"]
t.find('x')                                                                                                                                                                                                        
# => []

答案 1 :(得分:0)

这不是一个完整的答案。它只是处理前缀。

class Trie
  def find prefix
    expand(prefix, prefix.each_char.inject(@root, &:[])) rescue []
  end
  def expand prefix, affix
    #TODO
  end
end

鉴于t.find("maxi"),已实施的部分prefix.each_char.inject(@root, &:[])将返回:

{"m" => {
  :end => true,
  "i"  => {"m" => {"l" => {"i" => {"a" => {"n" => {:end => true}}}}}}
}}

并将前缀"maxi"传递给Trie#expand。然后,您需要扩展该哈希并将其与前缀组合。对于该部分,您可能需要参考答案here

答案 2 :(得分:0)

这是我的尝试

# Returns all the possible matching suffixes for the `given` string.
# trie is a map of map of .. strings delimitted by :end
# cur_word is a scratch pad for storing characters from prev level. 
# Pass empty string for cur_word or create a wrapper around this function.
def all_suffix(trie, given, cur_word)
   #Suffixes found in the current iteration
   suffixes = []


   #The current node (character at which we want the Hash)
   at = given[0] 

   cur_word << (at || '')

   cur_trie = trie[at] || trie[cur_word[-1]] || {}

   #When we are at the end of the string, given.length <= 1 and we must print out all suffixes
   cur_trie.each do |next_str, next_trie|

     if next_str == :end
       #Only if we reached the end of the `given` string
       suffixes << cur_word if given.length <= 1
     else
       #Delete the first character and continue iteration
       other_suffixes = all_suffix({ next_str => next_trie },
                              given[1..-1] || '',
                              cur_word + (given.length > 1 ? '' : next_str))

       suffixes << other_suffixes.flatten if other_suffixes.size > 0 
     end
   end
   suffixes.flatten
end 

trie = {
  "m"=>{"a"=>{"x"=>{
    :end=>true,
    "i"=>{"m"=>{
      :end=>true,
      "i"=>{"m"=>{"l"=>{"i"=>{"a"=>{"n"=>{:end=>true}}}}}}
    }},
    "w"=>{"e"=>{"l"=>{"l"=>{:end=>true}}}}
  }}}
}
  

p all_suffix(trie,“max”,“”)

["max", "maxim", "maximimlian", "maxwell"]    
  

p all_suffix(trie,“maxi”,“”)

["maxim", "maximimlian"]