2014-09-19 5 views
22

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

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

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

Но если искать, как выглядит во много раз «аа» в этой строке, я также получаю два.

string.count('aa') 
=> 2 

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

+2

Просьба уточнить (с правлением): '' aa'' появляется один или два раза в строке ''aaa''. –

+0

В этом случае, вероятно, должно быть два раза.Позиции 0 и 1 && Позиции 1 и 2 – Johnson

+0

Конечно, вы отличный плакат. Я вознаградил тебя, Кэри Шарлотта. – Johnson

ответ

26

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

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)/) 
    #=> ["", "", "", "", ""] 

# 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 
15

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

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

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

Я вижу, чтобы найти количество фактических строк, вы используете метод сканирования вместо метода count. Спасибо. – Johnson

+1

Да ['scan'] (http://www.ruby-doc.org/core-2.1.2/String.html#method-i-scan) принимает регулярное выражение типа'/aa/'или даже строку как '' aa "', если вы предпочитаете и возвращает совпадения. 'length' сообщает вам, сколько матчей, если вам все равно, что такое матчи. – tadman

+0

Вы также можете использовать счет или размер вместо длины – Johnson

Смежные вопросы