【问题标题】:ruby iterate through hashruby 遍历哈希
【发布时间】:2013-07-14 08:01:29
【问题描述】:

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

#<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"。如何按根获取此哈希中的所有单词?例如

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

【问题讨论】:

  • 没有时间得到完整的答案,但这里有一个线索可以解决找到前缀后剩下的问题:remaining = @root["m"]["a"]["x"]。您的 find 方法当然需要以编程方式发现它。 . .这是一个递归方法的练习——你需要两个,一个用来查找,另一个用来扩展剩余的
  • 第一个。我可以找到我需要的字符串。第二种递归查找其他匹配的方法有问题

标签: ruby algorithm trie


【解决方案1】:

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

给定:

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')                                                                                                                                                                                                        
# => []

【讨论】:

  • 你能解释一下inject声明吗?
  • @bsd 当然。它记录在here。在这种情况下,它使用来自start 的字母连续调用[] 上一次调用的结果(最初以@root 开头)。这是从'max'@root['m']['a']['x'] 的一种简单的编程方式。几个月前,有人(我很确定是@sawa)在另一个答案中像这样使用inject,我把它记在了记忆中,因为我发现这种用法非常优雅并且最初并不明显。
【解决方案2】:

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

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, &amp;:[])返回:

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

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

【讨论】:

  • 非常感谢你们。我得到了sawa's answer的工作解决方案,但接下来给了我更多的进步。伟大的工作
  • 没问题。 Darshan Computing 的答案是一个完整的答案。
【解决方案3】:

这是我的尝试

# 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"]

【讨论】:

    猜你喜欢
    • 2013-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 2016-02-27
    相关资源
    最近更新 更多