我正在尝试将所有可能的子串和它们的计数放入哈希中。 例如。
"abc" => { a: 1, b: 1, ab: 1, bc: 1}
为此,我编写了以下代码:
def get_all(b)
(0..(b.size-1)).to_a.combination(2).inject({}) { |h, g|
s = b[g[0],g[1]]
h[s] ? ( h[s] += 1) : ( h[s] = 1 )
h
}
end
但不知怎的,它无法正常工作,因为"abchh"
它返回:
{"a"=>1, "ab"=>1, "abc"=>1, "abch"=>1, "bc"=>1, "bch"=>1, "bchh"=>1, "chh"=>2, "hh"=>1}
chh
在那里两次,但我无法理解为什么。我错了什么?
谢谢!
答案 0 :(得分:2)
String#[]
,包括:
str[start, length] → new_str or nil str[range] → new_str or nil
前者需要 start 和 length ,而后者需要一个表示 start 和 end 的范围。< / p>
因此,而不是两个参数g[0]
和g[1]
:
b[g[0], g[1]]
你必须传递一个参数g[0]..g[1]
:
b[g[0]..g[1]]
此外,您还必须使用repeated_combination
来获取单个字符:
(0..2).to_a.combination(2).to_a
#=> [[0, 1], [0, 2], [1, 2]]
(0..2).to_a.repeated_combination(2).to_a
#=> [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
此外,您的代码可以简化:
a...b
代替a..(b-1)
each_with_object
而不是inject
,因此您无需从块中返回哈希Hash.new(0)
(i, j)
将元组数组分解为i..j
而不是g[0]..g[1]
示例:( indices
变量可以内联)
def get_all(str)
indices = (0...str.size).to_a.repeated_combination(2)
indices.each_with_object(Hash.new(0)) do |(i, j), h|
h[str[i..j]] += 1
end
end
或者,使用两个嵌套循环:
def get_all(str)
(0...str.size).each_with_object(Hash.new(0)) do |i, h|
(i...str.size).each do |j|
h[str[i..j]] += 1
end
end
end
也许这种方法已经做得太多了。我可能会把它分成两个方法:一个用于枚举子串,另一个用于计算它们。