我的Ruby计数器中的错误

时间:2017-07-25 00:13:23

标签: ruby

每个单词只计算一次。我希望它能告诉我每个单词出现的次数。

dictionary = ["to","do","to","do","to","do"]
string = "just do it to"

 def machine(word,list)
   initialize = Hash.new 

   swerve = word.downcase.split(" ")

     list.each do |i|
       counter = 0 

         swerve.each do |j|
           if i.include? j 
             counter += 1 
         end
       end
       initialize[i]=counter
     end
     return initialize
   end

 machine(string,dictionary)

5 个答案:

答案 0 :(得分:1)

您可以使用Array#count轻松地执行此操作:

def machine(word,list)
  word.downcase.split(' ').collect do |w|
    # for every word in `word`, count how many appearances in `list`
    [w, list.count { |l| l.include?(w) }]
  end.to_h
end

machine("just do it to", ["to","do","to","do","to","do"]) # => {"just"=>0, "do"=>3, "it"=>0, "to"=>3}

答案 1 :(得分:1)

我认为这是你正在寻找的东西,但似乎你正在向后逼近

将字符串“string”转换为数组,删除重复值并遍历每个元素,计算数组“dictionary”中的匹配数。可枚举方法:count在这里很有用。

这里输出的一个好的数据结构是散列,我们将字符串“string”中的唯一单词作为键存储,并将数组“dictionary”中这些单词的出现次数作为值存储。哈希允许人们在集合中存储有关数据的更多信息而不是数组或字符串,因此这适用于此。

dictionary = [ "to","do","to","do","to","do" ]

string = "just do it to"

def group_by_matches( match_str, list_of_words )

   ## trim leading and trailing whitespace and split string into array of words, remove duplicates.

   to_match = match_str.strip.split.uniq
   groupings = {}

   ## for each element in array of words, count the amount of times it appears *exactly* in the list of words array. 
   ## store that in the groupings hash

   to_match.each do | word |
     groupings[ word ] = list_of_words.count( word )
   end

   groupings
end

group_by_matches( string, dictionary ) #=>  {"just"=>0, "do"=>3, "it"=>0, "to"=>3}

另外,您应该考虑使用更具描述性的变量和方法名称来帮助自己和其他人跟踪正在发生的事情。

这似乎也让你倒退了。通常,您希望使用该数组来计算字符串中出现的次数。这似乎更接近现实世界的应用程序,您可以从预定义词列表中检查匹配的句子/数据串。

数组也很有用,因为它们是灵活的数据集合,可以通过可枚举的方法轻松迭代和变异。要处理字符串中的单词,正如您所看到的,最简单的方法是立即将其转换为单词数组。

有很多选择。如果你想缩短方法,可以用each_with_object调用或map调用替换更详细的每个循环,这将返回一个新对象,而不是像每个对象一样返回原始对象。在使用map.to_h的情况下,要小心,to_h将在二维数组[["key1", "val1"], ["key2", "val2"]]上工作,但不能在单维数组上工作。

## each_with_object

def group_by_matches( match_str, list_of_words )
  to_match = match_str.strip.split.uniq

  to_match.
    each_with_object( {} ) { | word, groupings | groupings[ word ] = list_of_words.count( word ) }
end

## map
def group_by_matches( match_str, list_of_words )
  to_match = match_str.strip.split.uniq

  to_match.
    map { | word | [ word, list_of_words.count( word ) ] }.to_h
end

根据性能,可读性和可靠性来衡量您的方法首选项。

答案 2 :(得分:1)

我认为,对于string中的每个单词,您希望确定dictionary中该单词的实例数。如果是这样,第一步是创建计算哈希

dict_hash = dictionary.each_with_object(Hash.new(0)) { |word,h| h[word] += 1 }
  #=> {"to"=>3, "do"=>3}

(我稍后会解释这段代码。)

现在在空格上拆分string并创建一个哈希,其键是字符串中的单词,其值是worddictionary的值出现的次数。

string.split.each_with_object({}) { |word,h| h[word] = dict_hash.fetch(word, 0) }
  #=> {"just"=>0, "do"=>3, "it"=>0, "to"=>3} 

这当然假设string中的每个单词都是唯一的。如果不是,根据所需的行为,一种可能性是使用另一个计数散列。

string = "to just do it to"
string.split.each_with_object(Hash.new(0)) { |word,h|
  h[word] += dict_hash.fetch(word, 0) }
  #=> {"to"=>6, "just"=>0, "do"=>3, "it"=>0}

现在让我解释一下上面的一些结构。

我使用类方法Hash::new的形式创建了两个哈希,它采用的参数等于所需的默认值,此处为零。这意味着如果

h = Hash.new(0)

h没有等于值word的密钥,则h[word]将返回h的默认值(以及散列{{ 1}}不会被改变)。以这种方式创建第一个哈希之后,我写了h。 Ruby将其扩展为

h[word] += 1

在她进行任何进一步处理之前。 h[word] = h[word] + 1 中传递给块的第一个单词是string(分配给块变量"to")。由于哈希word最初是空的(没有键),上面相等的右侧的h返回默认值零,给我们

h[word]

稍后,当h["to"] = h["to"] + 1 #=> = 0 + 1 => 1 再次等于word时,不会使用默认值,因为"to"现在有一个键h

"to"

我使用了陈旧的方法Enumerable#each_with_object。对于新手来说,这似乎很复杂。它不是。这条线

h["to"] = h["to"] + 1
  #=>   = 1 + 1 => 2

实际上 1 与以下相同。

dict_hash = dictionary.each_with_object(Hash.new(0)) { |word,h| h[word] += 1 }

换句话说,该方法允许人们编写一条创建,构造和返回哈希的行,而不是三行执行相同的操作。

请注意,我使用方法Hash#fetch从哈希值中检索值:

h = Hash.new(0)
dict_hash = dictionary.each { |word| h[word] += 1 }
h
如果dict_hash.fetch(word, 0) 的密钥不等于fetch的值,则会返回

0的第二个参数(此处为dict_hash)。相比之下,word在这种情况下会返回dict_hash[word]

1"有效"的原因是使用nil时,变量each_with_object的范围仅限于块,这通常是一种很好的编程习惯。不要担心,如果你还没有了解"范围"爱好。

答案 3 :(得分:0)

list.each do |i|
       counter = 0 

         swerve.each do |j|
           if i.include? j 
             counter += 1 

需要更改为

swerve.each do |i|
       counter = 0 

         list.each do |j|
           if i.include? j 
             counter += 1 

答案 4 :(得分:0)

您的代码会告诉单词/字符串中每个单词(字典中包含的单词)出现的次数。 如果要告知字典中每个单词出现的次数,可以切换list.each和swerve.each循环。然后,它将返回哈希#=> {"只是" => 0,"做" => 3,"它" => 0,"到" => ; 3}