Ruby - Anagram代码

时间:2016-10-05 09:04:37

标签: ruby anagram

我们在这里有一系列文字:

words =  ['demo', 'none', 'tied', 'evil', 'dome', 'mode', 'live',
          'fowl', 'veil', 'wolf', 'diet', 'vile', 'edit', 'tide',
          'flow', 'neon']

我的老师写了一个程序,打印出一组字谜词。字谜是单词中具有相同字母但按不同顺序排列的单词。输出应该如下所示:

["demo", "dome", "mode"]
["neon", "none"]
(etc)

这是我老师向我们展示的解决方案:

result = {}

words.each do |word|
  key = word.split('').sort.join
  if result.has_key?(key)
    result[key].push(word)
  else
    result[key] = [word]
  end
end

result.each do |k, v|
  puts "------"
  p v
end

我对这个程序的运作方式感到有点困惑,例如当这个部分设置为result[key].push(word)时,它所说的部分result[key] = [word]我知道这可能是个问题,但任何人都可以可以用外行的术语逐行解释解决方案,也可以像我一样理解假人。

PS。对不起新手在这里。

3 个答案:

答案 0 :(得分:2)

它基本上确保您在有效数组上运行。

当您从空哈希{}开始时,对于任何给定的密钥,result[key]的值将为nil - 因为密钥在该哈希中仍然不存在。

01:  if result.has_key?(key)
02:    result[key].push(word)
03:  else
04:    result[key] = [word]
05:  end

因此,第01行检查一个密钥是否已存在于result哈希中 - 如果是,那么,可以使用表达式result[key]访问它,并假设它是一个数组,将另一个单词输入那个阵列。

如果result哈希中仍然不存在密钥,则第04行通过分配一个单个元素数组[word]的值来设置它。

如果您对Ruby更熟悉,那么可以写下面的内容并避免整个if-else舞蹈:

words.each do |word|
  key = word.split('').sort.join
  result[key] ||= []
  result[key] << word
end

答案 1 :(得分:2)

请参阅内联评论说明:

words.each do |word| #=>  iterate each word in words array. "word" variable will have value at a particular iteration
  key = word
  .split('') #=> splits word, if word is 'demo' on iteration then it will be: `['d', 'e', 'm', 'o']`
  .sort #=> sorts the splitted array, i.e. the array above will be: `['e', 'd', 'm', 'o']`
  .join #=> joins the array sorted in above operation, it will be: 'edmo'. Since this is last operation, it will be returned and saved in `key` variable
  if result.has_key?(key) #=> Check whether result(Hash) already has key: `edmo`, returns true if present
    result[key].push(word) #=> result['edmo'] will give an array value, which can push word in that array
  else #=> false when key is not present in result Hash.
    result[key] = [word] #=> then add key with an array such as: `result['edmo] = ['demo']`
  end
end

但是,你可以用惯用的方式做同样的事情:

result = Hash.new{|h, k| h[k] =[] } #=> if key does not exist then the default value will be an array.

所以,上面的代码将成为:

words.each do |word|
  key = word.split('').sort.join
  result[key] << word # no need to validate whether we have key in Hash or not
end

但是,这种将值保持为数组的方法存在问题。如果我们的单词数组中有重复的单词,您的密钥中将有重复的数据。只需更改数组即可解决问题:

require 'set'
result = Hash.new{|h, k| h[k] = Set.new }

现在,我们都很好。

答案 2 :(得分:1)

程序通过对字母进行排序(key = word.split('').sort.join)来计算每个单词的键。如果两个或多个单词是彼此的字谜,则它们将具有相同的键。

例如,neonnone字样的关键字为enno

然后,在result哈希中添加单词。该哈希具有上面讨论的anagram键作为键。哈希值是单词(字符串)的数组。

这里注释了其他(重要)代码:

# If there is an entry in the hash for the current anagram key 
if result.has_key?(key)
  # Then add the current word in the array, together with all the
  # other anagrams that are already there (because they share the
  # same key)
  result[key].push(word)
else
  # If the key has not yet been created, then create it and assign
  # as a value a new array that only contains the current word.
  result[key] = [word]
end