dictionary = File.foreach('dictionary.txt').map { |line| line.split('\n') }
dictionary.each{|word|
puts word.length
if word.length == 5
puts word
end
}
It says the value for each |word| is only 1. Anyone have a clue why? Thanks.
You’re mapping a function that splits a line into lines to every line. Each line will contain one line, resulting in a one-element array. Maybe you meant line.chomp?
dictionary = File.foreach('dictionary.txt').map &:chomp
Related
I'm working on a practice problem in Ruby. I already have the answer (below) but I'm not sure I understand how exactly one part of the answer works, specifically, how does new_word evaluate to a string if |word| is in an array. I may just be overlooking something super basic here but would appreciate any help. Thanks!
Prompt:
Write a method abbreviate_sentence that takes in a sentence string and returns a new sentence where every word longer than 4 characters has all of its vowels removed.
Answer:
words = sent.split(" ")
new_words = []
words.each do |word|
if word.length > 4
new_word = abbreviate_word(word)
new_words << new_word
else
new_words << word
end
end
return new_words.join(" ")
end
def abbreviate_word(word)
vowels = "aeiou"
new_word = ""
word.each_char do |char|
if !vowels.include?(char)
new_word += char
end
end
return new_word
end
puts abbreviate_sentence("follow the yellow brick road") # => "fllw the yllw brck road"
puts abbreviate_sentence("what a wonderful life") # => "what a wndrfl life" ```
Courtesy of #ggorlen:
You're iterating over an array of strings, so each |word| isn't an array, it's a string. This code could be sent.split(" ").map {|e| e.size > 4 ? e.gsub(/[aeiou]/, "") : e}.join(" ")
I need to remove a reversed word from a Ruby array and I'm having issues with getting the correct output
I've tried a different way of looping, I've used exec.
# Were going to get the first line of input which is the length of the wordlist and coerce to type fixnum
pword_list_length = gets.chomp.to_i
# Initialize an empty array to hold pword_list_length
pword_list = Array.new
# loop until we have all the lines of input pushed into the array
pword_list_length.times do
pword_list.push(gets.chomp)
end
# Next were going to check to see what word we have both forward and backwards
pword_list.each do |word|
bword = word.reverse!
if pword_list.include? bword
print word.length
print bword[bword.length/2]
end
end```
```Expected Output:
3 y
Output
3y3c3e3y```
You are mutating list here:
bword = word.reverse!
reverse! will actually reverse content of variable word. After that list will sure include bword as you just made word reversed and assigned it to bword.
Use reverse (without !) to keep word unchanged.
I am trying to take a sentence, and reverse the positions of the letters in each word.
Below is my code that does not work:
def test(sentence)
array = []
array << sentence.split
array.collect {|word| word.reverse}
end
My problem is with:
array << sentence.split
It says it divides each word, but when I use interpolation, it reverses the whole sentence. Below is a similar code that works:
def test2
dog = ["Scout", "kipper"]
dog.collect {|name| name.reverse}
end
But it does not accept a sentence, and it already has the array defined.
I'm thinking you want to split, then map each element of the array to its reversed version then rejoin the array into a string:
def test(sentence)
sentence.split.map {|word| word.reverse}.join(" ")
end
More concise using symbol-to-proc (credit #MarkThomas in comments)
sentence.split.map(&:reverse).join " "
Unlike methods that break up the sentence into words, reverses each word and then rejoins them, the use of Array#gsub with a regular expression preserves non-word characters (such as the comma in the example below) and multiple spaces.
"vieille, mère Hubbard".gsub(/\b\p{L}+\b/, &:reverse)
#=> "ellieiv, erèm drabbuH"
def reverse(str)
str.split.map { |s| s.length < 5 ? s : s.reverse }.join(' ')
end
puts reverse ("this is a catalogy")
This should reverse each word thats length upto 5
I am trying to sort an array of words by their last character.
def array_sort_by_last_letter_of_word(array)
list = array[-1,1]
list.sort { |a,b| b <=> a }
end
puts array_sort_by_last_letter_of_word ['sky', 'puma', 'maker']
The output I get is just "maker".
def array_sort_by_last_letter_of_word(array)
array.sort_by { |word| word[-1] }
end
Rails version (using String#last):
def array_sort_by_last_letter_of_word(array)
array.sort_by(&:last)
end
Andrey's answer is definitely the way to do this. But to understand what's going wrong with your code:
list = array[-1,1]
This syntax is for getting a subarray of an array. The pattern is array[start, length] to get an array starting at index start with length length. So you are asking for an array starting at -1 (which means the last index) of length 1 i.e. just the last element of the array. So last = ['maker']. That's why your sort method is just returning that element.
You want to get the last character inside the sort block, which is what determines how strings are compared
array.sort { |a,b| a[-1] <=> b[-1] }
Also note that a needs to be left of b, otherwise the array is sorted in reverse.
I need to remove any strings from an array that are not of a certain length. The assignment recommends using map or map!. I have been playing with map!, delete_if, and keep_if, but I am getting nowhere. Can anyone help me? Below is one of my attempts:
dictionary = Array.new
file = File.open("words.txt").each do | line |
dictionary.push line
end
(wordlength = gets)
wordlength = wordlength.to_i
dictionary = dictionary.reject {|word| word.length != wordlength }
puts dictionary
You need to remove whitespaces from your input:
dictionary.push line.strip
By the way, the code for reading your file can be simplified:
dictionary = File.readlines("words.txt").map { |line| line.strip }
(As for the original question, both delete_if and reject/reject! work)
EDIT
The complete code could be something like this:
#!/usr/bin/env ruby
dictionary = File.readlines("words.txt").map { |line| line.strip }
wordlength = gets.to_i
dictionary.delete_if { |word| word.length != wordlength }
puts dictionary #test
Keep in mind that reject! and delete_if change the original array, so if you want to keep the original values you should use
new_dictionary = dictionary.reject { |word| word.length != wordlength }
or even
new_dictionary = dictionary.select {|word| word.length == wordlength }
You should need to use Array#delete_if.
dictionary.delete_if{|s| s.size != wordlength }
I'd go with #reject here.
dictionary = ["apple", "bug", "cup", "drain"]
dictionary.reject {|word| word.length != 3}
This code should work:
#!/usr/bin/env ruby
dictionary = File.open("words.txt").map do |line|
line.strip # remove line end and whitespaces at the beginning and the end of the line
end
wordlength = gets
wordlength = wordlength.to_i
dictionary = dictionary.reject { |word| word.length != wordlength }
puts dictionary #test
Some comments as it is your first ruby program ever:
It's more common in ruby to add items to an array using << operator.
You can use map method to transform each item in an array into something else and return an array of the transformed items.
Instead of delete_if or keep_if I'd just group the words by length:
file = "/usr/share/dict/words"
words = File.readlines(file).map { |line| line.chomp }.group_by(&:length)
This makes it trivial to retrieve words with different lengths:
words[5] # all words with length 5
#=> ["aalii", "Aaron", "abaca", "aback", "abaff", "abaft", "Abama", "abase", "abash", "abask", ...]
words[10] # all words with length 10
#=> ["abalienate", "abaptiston", "abasedness", "abbeystede", "abbreviate", "abdication", "abdicative", "abdominous", "aberdevine", "Aberdonian", ...]
|word| here is different from i as you would use in C++. i would be referring to the index of the object in dictionary. |word| here refers directly to the object in the dictionary array. e.g.
dictionary = ["animal", "animate"]
|word| would refer to the object "animal", i would refer to index 0 of dictionary. To make it clearer, Ruby even has a enumerable method:
.each_with_index do |element, index|
end
where |element| refers to the object, and |index| refers to the index of the object.
I don't recommend deleting through the very array that you're iterating through, it comes out with quirky results since the size of your array changes each time you delete an element.
Arup's suggestion of using delete_if should work fine. If that doesn't work, you can try another method (albeit less efficient) by setting each |word| equal to nil if it's length != wordlength, then compacting it (removing objects that are equal to nil).
dictionary = []
file = File.open("words.txt").each do | line |
dictionary << line.strip #strip removes whitespaces and newlines
end
wordlength = gets.chomp.to_i #chomp removes any newlines "\n"
dictionary = dictionary.each do |word|
word = nil if word.length != wordlength
end
puts dictionary.compact!