繁体   English   中英

如何计算Ruby字符串中唯一的多个单词?

[英]How do I count unique multiple words in a Ruby string?

尝试编写将对唯一单词计数并返回其总出现次数的Ruby代码。

因此,假设我想在下面的句子中找到Sally,Marina和Tina的出现次数:“星期一Tina会见Sally和Harris。然后Tina会拜访她的妈妈Marina。Marina和Tina会见David吃晚饭。”

我尝试了以下方法,但这击败了干本人。 有没有更好的办法?

string = "Monday Tina will meet Sally and Harris. Then Tina will visit her mom Marina. Marina and Tina will meet David for dinner. Sally will then take Tina out for a late night party." 

puts "Marina appears #{string.split.count("brown").to_i} times."
puts "Tina appears #{string.split.count("grey").to_i} times."
puts "Sally appears #{string.split.count("blue").to_i} times."

预期结果:程序在文本中查找唯一的单词并将其返回。

实际:我必须在其自己的PUTS行上对每个唯一单词进行硬编码,并执行string.split.count(用于该唯一单词)

注意:我尝试了以下操作,但这给了我每个单词。 我需要对其进行优化,以使其仅满足我的要求。 这就是我在努力的地方。

def cw(string)
  w = string.split(' ')
  freq = Hash.new(0)
  w.each { |w| freq[w.downcase] += 1 }
  return freq
end
puts cw(string)
def count_em(str, who)
  str.gsub(/\b(?:#{who.join('|')})\b/i).
      each_with_object(Hash.new(0)) { |person,h| h[person] += 1 }
end

str = "Monday Tina will meet Sally and Harris. Then Tina will visit her " +
      "mom Marina. Marina and Tina will meet David for dinner. Sally will " +
      "then take Tina out for a late night party." 

who = %w| Sally Marina Tina |

count_em(str, who)
  #> {"Tina"=>4, "Sally"=>2, "Marina"=>2}

第一步如下。

r = /\b(?:#{who.join('|')})\b/i
  #=> /\b(?:Sally|Marina|Tina)\b/i
enum = str.gsub(r)
  #=> #<Enumerator: "Monday Tina will meet Sally and Harris. Then
  #   ...
  #   for a late night party.":gsub(/\b(?:Sally|Marina|Tina)\b/i)>

我们可以将其转换为数组,以查看将传递给each_with_object的值。

enum.to_a
  #=> ["Tina", "Sally", "Tina", "Marina", "Marina", "Tina", "Sally", "Tina"]

然后,我们只计算enum生成的唯一值的实例数。

enum.each_with_object(Hash.new(0)) { |person,h| h[person] += 1 }
  #=> {"Tina"=>4, "Sally"=>2, "Marina"=>2}

请参阅String#gsub ,尤其是只有一个参数且没有任何块的情况。 公认这是gsub的不寻常用法,因为它没有进行替换,但是在这里我更喜欢String#scan因为gsub返回一个枚举器,而scan产生一个临时数组。

另请参见Hash :: new ,其中new接受参数且不阻塞。 该参数称为默认值 如果h是这样定义的哈希,则如果h没有键k ,则默认值由h[k]返回。 哈希值不会改变。

此处的默认值为零。 当表达式h[person] += 1被解析时,它将转换为:

h[person] = h[person] + 1

如果person等于"Tina" ,并且这是枚举器首次生成"Tina"并将其传递给块,则h将没有键"Tina" ,因此表达式变为:

h["Tina"] = 0 + 1

默认值为0 下次将"Tina"传递到块时,哈希具有键"Tina" (值为1 ),因此将执行以下计算。

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

仅获取所需的人员姓名:

people = ['Marina', 'Tina', 'Sally', 'Dory']
tmp = string.scan(/\w+/).keep_if{ |w| people.include? w }
counts people.map{ |name| [name, tmp.count{|n| n == name }] }.to_h
counts #=> {"Marina"=>2, "Tina"=>4, "Sally"=>2, "Dory"=>0}

这个映射peopole针对阵列tmp含有嵌套数组[name, count] ,然后被转换成一个散列。

好处是,如果没有人出现,则返回0 ,请参阅'Dory'


要获得总数,可以通过两种方法:

 tmp.size #=> 8 counts.values.sum #=> 8 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM