[英]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.