Подтвердить что ты не робот

Ruby: Как подсчитать количество строк, появляющихся в строке?

Я пытаюсь подсчитать количество строк строки в другой строке.

Я знаю, вы можете подсчитать количество раз, когда в строке появляется буква:

string = "aabbccddbb"
string.count('a')
=> 2

Но если я ищу, сколько раз "aa" появляется в этой строке, я также получаю два.

string.count('aa')
=> 2

Я не понимаю этого. Я помещаю значение в кавычки, поэтому я ищу число раз, когда появляется точная строка, а не только буквы.

4b9b3361

Ответ 1

Вот несколько способов подсчитать количество раз, когда данная строка отображается в строке (первая из которых является моим предпочтением). Примечание (как подтверждено OP) подстрока 'aa' появляется дважды в строке 'aaa', и поэтому пять раз в:

string="aaabbccaaaaddbb"

# 1

Используйте String # scan с регулярным выражением, которое содержит положительный lookahead, который ищет подстроку:

def count_em(string, substring)
  string.scan(/(?=#{substring})/).count
end

count_em(string,"aa")
 #=> 5

Примечание:

"aaabbccaaaaddbb".scan(/(?=aa)/)
  #=> ["", "", "", "", ""]

Положительный lookbehind дает тот же результат:

"aaabbccaaaaddbb".scan(/(?<=aa)/)
  #=> ["", "", "", "", ""]

# 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

Ответ 2

Это потому, что count подсчитывает символы, а не экземпляры строк. В этом случае 'aa' означает то же, что и 'a', он считал набор символов для подсчета.

Чтобы подсчитать количество строк aa в строке:

string = "aabbccddbb"
string.scan(/aa/).length
# => 1
string.scan(/bb/).length
# => 2
string.scan(/ff/).length
# => 0