Как человек, который учится на инженера-программиста, я столкнулся со многими упражнениями по программированию. Программистам чаще всего приходится решать задачи по кодированию, не прибегая к наиболее очевидному и прямому решению(например, перевернуть строку без использования обратного метода).

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

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

Давайте начнем.

Если вы здесь, то, скорее всего, вы столкнулись с подсказкой, которая говорит что-то вроде —

"Определите метод, который принимает текст. Метод также должен возвращать хэш с подсчетом количества раз, когда каждое слово указано в строке».

Очевидно, что .tally не подходит, так что давайте перейдем к решению.

  1. Сначала мы хотим иметь пару строк, чтобы мы могли понять, как это будет выглядеть. Вы можете открыть любой редактор кода по вашему выбору и перейти в пустой документ. Для этого примера я приведу пару слов ниже.
puts ["Loki", "Loki", "Thor", "Iron Man", "Hulk", "Incredible Hulk", "loki"].tally

puts ["Yoda", "Mace Windu", "Obi-Wan", "Yoda", "Anakin Skywalker", "Luke", "Darth Vader"].tally

puts ["Sally", "sells", "sea", "shells", "at", "the", "sea", "shore"].tally

(Не стесняйтесь скопировать это в свой текстовый редактор и посмотреть результат. Чем более вы интерактивны, тем больше шансов, что это останется с вами.)

2. Если вы запустите код, то вы увидите и выведете его примерно так:

{"Loki"=>2, "Thor"=>1, "Iron Man"=>1, "Hulk"=>1, "Incredible Hulk"=>1, "loki"=>1}

{"Yoda"=>2, "Mace Windu"=>1, "Obi-Wan"=>1, "Anakin Skywalker"=>1, "Luke"=>1, "Darth Vader"=>1}

{"Sally"=>1, "sells"=>1, "sea"=>2, "shells"=>1, "at"=>1, "the"=>1, "shore"=>1}

3. Теперь, когда мы знаем, как выглядит искомый вход, давайте начнем испытание.

4. Что касается меня, я предпочитаю начинать с чтения подсказки и записывая первое, что приходит на ум, что может повлечь за собой упражнение. В первом предложении говорится:
"Определите метод, который принимает текст".

Мой мозг сразу же приходит к этому —

def word_count(text)

end

5. Мы знаем, что параметр принимает строку, так как же преобразовать эту строку в другой класс, который упростит решение этого упражнения? ДЛЯ МЕНЯ я хочу сначала превратить строку в массив. Итак, я сделаю это:

def word_count(text)
  sentence = text.split

end

Давайте разберем это. Почему я использовал параметр .split. Ну, это входит в то, что я искал. Я хочу превратить строку в массив. Когда мы смотрим на вывод, мы получаем следующее:

p word_count("Where is Gamora? Who is Gamora? Why is Gamora?")

=> ["Where", "is", "Gamora?", "Who", "is", "Gamora?", "Why", "is", "Gamora?"]
p word_count("Where is Gamora? Who is Gamora? Why is Gamora?").class

=> Array

Когда мы используем метод .class, мы видим, что он превратил строку в массив, так что давайте двигаться дальше.

Следующая строка кода будет выглядеть примерно так:

def word_count(text)
    sentence = text.split
    sentence.group_by(&:itself)
 end

 p word_count("Where is Gamora? Who is Gamora? Why is Gamora?")

Хорошо. Почему я использовал метод .group_by? Что ж, метод .group_by ведет нас в правильном направлении к тому, чего мы хотим. Он группирует параметр, но не в правильном формате. Вывод выглядит следующим образом:

=> {"Where"=>["Where"], 
"is"=>["is", "is", "is"], 
"Gamora?"=>["Gamora?", "Gamora?", "Gamora?"], 
"Who"=>["Who"], "Why"=>["Why"]}

Очень-очень уродливо и совсем не СУХО, но это то, что мы ищем, и это действительно превратило массив в хэш. Если мы подсчитаем, сколько раз слова повторяются, код будет выглядеть так, как показано выше. «Где» = 1. «есть» = 3, «Гамора?» = 3, «Кто» = 1 и «Почему» = 1. Это на правильном пути, но он просто выводит намного больше, чем мы ищем, а это означает, что нам нужно добавить еще один шаг, чтобы наконец получить то, что мы хотим.

def word_count(text)
    sentence = text.split
    sentence.group_by(&:itself).transform_values(&:count)
 end

 puts word_count("Where is Gamora? Who is Gamora? Why is Gamora?")

=> {"Where"=>1, "is"=>3, "Gamora?"=>3, "Who"=>1, "Why"=>1}

Добавление .transform_values(&:count) дает нам именно то, что мы ищем, когда запускаем код.

Чтобы разбить его, если бы мы просто оставили .transform_values ​​сам по себе, то он вывел бы что-то совершенно другое и далекое от того, что мы ищем.

def word_count(text)
    sentence = text.split
    sentence.group_by(&:itself).transform_values
 end

 puts word_count("Where is Gamora? Who is Gamora? Why is Gamora?")

=> #<Enumerator:0x0000000105140d60>

Это совсем не то, что мы искали, поэтому (&:count) дал нам правильный формат для прохождения этой задачи кодирования.

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

Если вас интересуют еще подобные статьи, ставьте палец вверх и подписывайтесь. Спасибо и желаю удачи на вашем пути к кодированию!