如何计算 Ruby 字符串中唯一的多个单词?
How do I count unique multiple words in a Ruby string?
正在尝试编写一个 Ruby 代码来计算唯一单词和 return 它们的总出现次数。
所以假设我想在下面的句子中查找 Sally、Marina 和 Tina 的出现次数 "Monday Tina will meet Sally and Harris. Then Tina will visit her mom Marina. Marina and Tina will meet David for dinner."
我尝试了以下方法,但这打败了干校长。有没有更好的办法?
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."
预期结果:程序在文本中查找独特的单词并 returns 它们。
实际:我必须在其自己的 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)
只获取所需的人名:
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]
的嵌套数组,然后转换为散列。
好的是returns0
人不出现,见'Dory'
。
要获得总数,有两种方法:
tmp.size #=> 8
counts.values.sum #=> 8
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
returns 是一个枚举器,而 scan 生成一个临时数组.
另请参阅 Hash::new,其中 new
接受参数且没有块的情况。该参数称为 默认值 。如果 h
是这样定义的散列,如果 h
没有键 k
,则 h[k]
返回默认值。哈希没有改变。
此处默认值为零。当表达式 h[person] += 1
被解析时,它被转换为:
h[person] = h[person] + 1
如果person
等于"Tina"
,并且是枚举器第一次生成"Tina"
传递给block,h
不会有key "Tina"
,所以表达式变成:
h["Tina"] = 0 + 1
因为 0
是默认值。下一次将 "Tina"
传递给区块时,哈希有一个键 "Tina"
(值为 1
),因此执行以下计算。
h["Tina"] = h["Tina"] + 1 #=> 1 + 1 #=> 2
正在尝试编写一个 Ruby 代码来计算唯一单词和 return 它们的总出现次数。
所以假设我想在下面的句子中查找 Sally、Marina 和 Tina 的出现次数 "Monday Tina will meet Sally and Harris. Then Tina will visit her mom Marina. Marina and Tina will meet David for dinner."
我尝试了以下方法,但这打败了干校长。有没有更好的办法?
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."
预期结果:程序在文本中查找独特的单词并 returns 它们。
实际:我必须在其自己的 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)
只获取所需的人名:
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]
的嵌套数组,然后转换为散列。
好的是returns0
人不出现,见'Dory'
。
要获得总数,有两种方法:
tmp.size #=> 8
counts.values.sum #=> 8
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
returns 是一个枚举器,而 scan 生成一个临时数组.
另请参阅 Hash::new,其中 new
接受参数且没有块的情况。该参数称为 默认值 。如果 h
是这样定义的散列,如果 h
没有键 k
,则 h[k]
返回默认值。哈希没有改变。
此处默认值为零。当表达式 h[person] += 1
被解析时,它被转换为:
h[person] = h[person] + 1
如果person
等于"Tina"
,并且是枚举器第一次生成"Tina"
传递给block,h
不会有key "Tina"
,所以表达式变成:
h["Tina"] = 0 + 1
因为 0
是默认值。下一次将 "Tina"
传递给区块时,哈希有一个键 "Tina"
(值为 1
),因此执行以下计算。
h["Tina"] = h["Tina"] + 1 #=> 1 + 1 #=> 2