Как человек, который учится на инженера-программиста, я столкнулся со многими упражнениями по программированию. Программистам чаще всего приходится решать задачи по кодированию, не прибегая к наиболее очевидному и прямому решению(например, перевернуть строку без использования обратного метода).
Я столкнулся с этой уникальной ситуацией не потому, что принимал участие в соревновании по программированию, а потому, что работал на старой версии Ruby, где не существовало метода .tally.
Я знаю, что есть еще много людей, которые учатся программировать и могут столкнуться с устаревшей версией ruby для определенного проекта, такого как я, поэтому вот небольшая помощь на случай, если кто-то окажется в той же лодке, что и я.
Давайте начнем.
Если вы здесь, то, скорее всего, вы столкнулись с подсказкой, которая говорит что-то вроде —
"Определите метод, который принимает текст. Метод также должен возвращать хэш с подсчетом количества раз, когда каждое слово указано в строке».
Очевидно, что .tally не подходит, так что давайте перейдем к решению.
- Сначала мы хотим иметь пару строк, чтобы мы могли понять, как это будет выглядеть. Вы можете открыть любой редактор кода по вашему выбору и перейти в пустой документ. Для этого примера я приведу пару слов ниже.
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. Несколько строк кода и мы получили именно то, что искали. Не стесняйтесь изменять строку и передавать все, что вы хотите проверить.
Если вас интересуют еще подобные статьи, ставьте палец вверх и подписывайтесь. Спасибо и желаю удачи на вашем пути к кодированию!