文字列が別の文字列に出現する回数をカウントしようとしています。
文字が文字列に出現する回数をカウントできることは知っています。
string = "aabbccddbb"
string.count('a')
=> 2
しかし、この文字列に「aa」が何回現れるかを検索すると、2つも取得されます。
string.count('aa')
=> 2
これはわかりません。値を引用符で囲むため、文字だけでなく、正確な文字列が表示される回数を検索しています。
特定の部分文字列が文字列に出現する回数を数える方法は次のとおりです(最初は私の好みです)。 (OPによって確認されたように)部分文字列'aa'
は、文字列'aaa'
、したがって5回:
string="aaabbccaaaaddbb"
#1
String#scan を使用して、サブストリングを探す正の先読みを含む正規表現を使用します。
def count_em(string, substring)
string.scan(/(?=#{substring})/).count
end
count_em(string,"aa")
#=> 5
注意:
"aaabbccaaaaddbb".scan(/(?=aa)/)
#=> ["", "", "", "", ""]
肯定的な後読みでも同じ結果が得られます。
"aaabbccaaaaddbb".scan(/(?<=aa)/)
#=> ["", "", "", "", ""]
同様に、 String#scan
は、 String#gsub に置き換えることができます。
#2
配列に変換し、 Enumerable#each_cons を適用してから、結合してカウントします。
def count_em(string, substring)
string.each_char.each_cons(substring.size).map(&:join).count(substring)
end
count_em(string,"aa")
#=> 5
我々は持っています:
enum0 = "aaabbccaaaaddbb".each_char
#=> #<Enumerator: "aaabbccaaaaddbb":each_char>
この列挙子を配列に変換することにより、この列挙子によって生成される要素を確認できます。
enum0.to_a
#=> ["a", "a", "a", "b", "b", "c", "c", "a", "a", "a",
# "a", "d", "d", "b", "b"]
enum1 = enum0.each_cons("aa".size)
#=> #<Enumerator: #<Enumerator: "aaabbccaaaaddbb":each_char>:each_cons(2)>
変換enum1
を配列に追加して、列挙子がmap
に渡す値を確認します。
enum1.to_a
#=> [["a", "a"], ["a", "a"], ["a", "b"], ["b", "b"], ["b", "c"],
# ["c", "c"], ["c", "a"], ["a", "a"], ["a", "a"], ["a", "a"],
# ["a", "d"], ["d", "d"], ["d", "b"], ["b", "b"]]
c = enum1.map(&:join)
#=> ["aa", "aa", "ab", "bb", "bc", "cc", "ca",
# "aa", "aa", "aa", "ad", "dd", "db", "bb"]
c.count("aa")
#=> 5
これは、文字列のインスタンスではなく、 count
がカウント文字であるためです。この場合、'aa'
は'a'
と同じことを意味し、カウントする文字のセットと見なされます。
文字列にaa
が現れる回数を数えるには:
string = "aabbccddbb"
string.scan(/aa/).length
# => 1
string.scan(/bb/).length
# => 2
string.scan(/ff/).length
# => 0