Skip to content

Instantly share code, notes, and snippets.

@GermanHoyos
Forked from PamBWillenz/Each With Index
Created March 4, 2018 00:04
Show Gist options
  • Save GermanHoyos/c19a9ae3f607d65ce1120414f2389b13 to your computer and use it in GitHub Desktop.
Save GermanHoyos/c19a9ae3f607d65ce1120414f2389b13 to your computer and use it in GitHub Desktop.
Loops - Bloc Checkpoint
INSTRUCTIONS
[2,4,6].each_with_index do |element, index|
p "#{element} is at position #{index}"
end
Write a method, add_value_and_index, that takes an array of numbers and returns a new array composed of the value-plus-the-index of each element in the argument array:
add_value_and_index([2,4,6])
#=> 2,5,8
SPECS
describe '#add_value_and_index' do
it "returns a new array composed of the value + index of each element in the former" do
expect( add_value_and_index([2,1,0]) ).to eq([2,2,2])
end
end
CODE
def add_value_and_index(array)
new_array = []
array.each_with_index do |element, index|
p "#{element} is at position #{index}"
new_array << element + index
end
new_array
end
EXAMPLE
def what_number_are_we_on?(array)
new_array = []
array.each do |num|
new_array << "We're on number: #{num}"
end
new_array
end
first_array = [2, 4, 6, 8]
#=> [2, 4, 6, 8]
second_array = what_number_are_we_on?(first_array)
first_array
#=> [2, 4, 6, 8]
second_array
#=> ["We're on number: 2",
"We're on number: 4",
"We're on number: 6",
"We're on number: 8"]
Note that we have to declare new_array as an empty array before "shoveling" items into it. Otherwise, Ruby wouldn't know to treat it as an instance of Array.
INSTRUCTIONS
class ArrayModifier
end
class StringModifier
end
Create an ArrayModifier class. It should take an array as an argument to its initialize function, and have one instance method:
exclaim -- Loops through the array of strings and returns a new array. The new array will consist of the elements of the original array concatenated with a "!".
For example:
array = ["I would walk 500 miles", "And I would walk 500 more"]
ArrayModifier.new(array).exclaim
#=> ["I would walk 500 miles!",
"And I would walk 500 more!"]
To "collect" the results of looping and return those results, our exclaim method should follow a similar pattern as the what_number_are_we_on? method above: Initialize a new array, add members to it, and return it at the end of the loop.
But our exclaim method doesn't do The Proclaimers justice. To fix this, write a StringModifier class that takes a string on initialization. Give the class a single instance method:
proclaim - Splits the string into an array of separate words, adds an exclamation mark to each, then joins them back together with spaces and returns the new string.
StringModifier.new("I would walk 500 miles").proclaim
#=> "I! would! walk! 500! miles!"
Hint: You'll want to use the split method on the string to turn it into an array. You'll need to turn the array back into a string at the end of the method. Reference the join method for how to convert an array into a string.
Write a capsify method on ArrayModifier which uses Ruby's String#upcase to upcase all the elements of the array.
array = ["I would walk 500 miles", "And I would walk 500 more"]
ArrayModifier.new(array).capsify
#=> ["I WOULD WALK 500 MILES",
"AND I WOULD WALK 500 MORE"]
Use ArrayModifier#exclaim inside your StringModifier#proclaim method to make the latter method one line long!
CODE
class ArrayModifier
attr_accessor :array
def initialize(array)
@array = array
end
def exclaim
new_array = []
@array.each do |string|
new_array << "#{string}!"
end
new_array
end
def capsify
new_array = []
@array.each do |string|
new_array << "#{string.upcase}"
end
new_array
end
end
p array = ["I would walk 500 miles", "And I would walk 500 miles more"]
p new_array = ArrayModifier.new(array).capsify
p new_array = ArrayModifier.new(array).exclaim
class StringModifier
attr_accessor :string
def initialize(string)
@string = string
end
def proclaim
new_array = []
@string.split.each do |word|
new_array << "#{word}!"
end
new_array.join(' ')
end
end
p string = "I would walk 500 miles, And I would walk 500 miles more"
p StringModifier.new(string).proclaim
RESULTS
ArrayModifier#exclaim adds an exclamation mark to each element
ArrayModifier#exclaim doesn't modify the original array
ArrayModifier#capsify uppercases each element
ArrayModifier#capsify doesn't modify the original array
StringModifier#proclaim adds an exclamation mark after each word
OUTPUT
["I would walk 500 miles", "And I would walk 500 miles more"]
["I WOULD WALK 500 MILES", "AND I WOULD WALK 500 MILES MORE"]
["I would walk 500 miles!", "And I would walk 500 miles more!"]
"I would walk 500 miles, And I would walk 500 miles more"
"I! would! walk! 500! miles,! And! I! would! walk! 500! miles! more!"
INSTRUCTIONS
Write a Title class which is initialized with a string.
It has one method -- fix -- which should return a title-cased version of the string:
Title.new("a title of a book").fix
#=> A Title of a Book
You'll need to use conditional logic - if and else statements - to make this work. Make sure you read the test specification carefully so you understand the conditional logic to be implemented.
Some methods you'll want to use:
String#downcase
String#capitalize
Array#include?
You might also want to use each_with_index to detect when you're on the first word, which should always be capitalized.
SPECS
describe "Title" do
describe "fix" do
it "capitalizes the first letter of each word" do
expect( Title.new("the great gatsby").fix ).to eq("The Great Gatsby")
end
it "works for words with mixed cases" do
expect( Title.new("liTTle reD Riding hOOD").fix ).to eq("Little Red Riding Hood")
end
it "downcases articles" do
expect( Title.new("The lord of the rings").fix ).to eq("The Lord of the Rings")
expect( Title.new("The sword And The stone").fix ).to eq("The Sword and the Stone")
expect( Title.new("the portrait of a lady").fix ).to eq("The Portrait of a Lady")
end
it "works for strings with all uppercase characters" do
expect( Title.new("THE SWORD AND THE STONE").fix ).to eq("The Sword and the Stone")
end
end
end
CODE
class Title
def initialize(string)
@string = string
end
def fix
articles = ["the", "of", "a", "an", "and"]
fix_words = []
@string.downcase.split.each_with_index do |word, index|
if index > 0 && articles.include?(word)
fix_words << word
else
fix_words << word.capitalize
end
end
fix_words.join(" ")
end
end
RESULTS
Results
Title fix capitalizes the first letter of each word
Title fix works for words with mixed cases
Title fix downcases articles
Title fix works for strings with all uppercase characters
EXPLANATION FROM STACK OVERFLOW
I like to break these types of problems up into smaller chunks of logic to help me understand before I write an algorithm. In this case you need to modify each word of the string based on some rules.
If it's the first word, capitalize it.
If it's not a special word, capitalize it.
If it's a special word AND it's not the first word, downcase it.
With these rules you can write your logic to follow.
special_words = ['a', 'an', 'and', 'of', 'the']
fixed_words = []
@string.downcase.split.each_with_index do |word, index|
# If this isn't the first word, and it's special, use downcase
if index > 0 and special_words.include?(word)
fixed_words << word
# It's either the first word, or not special, so capitalize
else
fixed_words << word.capitalize
end
end
fixed_words.join(" ")
You'll notice I'm using downcase on the string before calling split and each_with_index. This is so that all the words get normalized a downcase and can be easily checked against the special_words array.
I'm also storing these transformed words in an array and joining them back together in the end. The reason for that, is if I try to use downcase! or capitalize! on the split strings, I'm not modifying the original title string.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment