Ruby - 字谜代码

Posted

技术标签:

【中文标题】Ruby - 字谜代码【英文标题】:Ruby - Anagram Codes 【发布时间】:2017-02-13 15:31:33 【问题描述】:

我们这里有一个单词数组:

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。在这里对不起新手。

【问题讨论】:

惹恼你的老师! result = words.group_by|word| word.chars.sort.join 【参考方案1】:

查看解释内嵌注释:

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】:

它基本上可以确保您在有效的数组上进行操作。

当您从空哈希 开始时,对于任何给定键,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哈希中仍然不存在key,那么,第04行通过分配一个值来设置它,该值是一个单元素数组[word]


如果你更熟悉 Ruby,那么,可以写下类似下面的内容,避免整个 if-else 跳舞:

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

【讨论】:

这也可以用result[key] ||= []; result[key].push(word)这样的东西更明确 你可以像Hash.new|k, v| k[v] = []这样预定义散列【参考方案3】:

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

例如neonnone这两个词的key是enno

然后,将单词添加到result 哈希中。该散列以上面讨论的字谜键作为键。哈希值是单词(字符串)的数组。

这是注释的(重要)代码的其余部分:

# 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

【讨论】:

以上是关于Ruby - 字谜代码的主要内容,如果未能解决你的问题,请参考以下文章

从数组中删除仅大小写不同的字符串值(Ruby)

Ruby 字谜求解器 [关闭]

ruby 字谜

你怎么能找到一个单词的所有字谜?

如何让这个 Javascript 字谜算法在 Ruby 中工作?

在 ruby​​ 中解决 Hackerrank 的字谜解决方案