2

I am trying to return all words which have more than four letters in the below exercise.

def timed_reading(max_length, text)
  var_b = text.split(" ")

  var_b.map do |i|
    if i.length >= max_length
      return i
    end
  end
end

print timed_reading(4,"The Fox asked the stork, 'How is the soup?'")
# >> asked

I seem to get only one word.

5
  • 4
    Unrelated, but meaningful variable names go a long way, e.g., words and word have much more meaning than var_b and i. In any case, you're returning from the function as soon as you hit the first word longer than max_length. And you don't want map, you want to gather only those elements that meet the requirement: map will create a value for every object in the array it's called on. Commented Sep 19, 2018 at 20:19
  • Another thing is to use split(/\s+/) to split on one or more spaces as well. Commented Sep 19, 2018 at 20:20
  • 1
    ...and I think min_length would be a better choice for the variable name than max_length, since you want to select words whose length is at least a a given minimum value. Commented Sep 19, 2018 at 20:34
  • 2
    @tadman, or just split with no argument. Commented Sep 19, 2018 at 21:22
  • 1
    You state, "...words which have more than 4 letters.". To be consistent with your code that should be "...words which have 4 or more letters.". Commented Sep 19, 2018 at 22:19

2 Answers 2

4

If you want to filter a list and select only certain kinds of entries, use the select method:

var_b.select do |i|
  i.length >= max_length
end

Where that's all you need.

The return i in the middle is confusing things, as that breaks out of the loop and returns a single value from the method itself. Remember that in Ruby, unlike others such as JavaScript, return is often implied and doesn't need to be spelled out explicitly.

Blocks don't normally have return in them for this reason unless they need to interrupt the flow and break out of the method itself.

Sign up to request clarification or add additional context in comments.

1 Comment

Many thanks. All makes sense now (and of course works)
2

You don't need to first extract all words from the string and then select those having at least four letters. Instead you can just extract the desired words using String#scan with a regular expression.

str = "The Fox asked the stork, 'How is the soup?'? Très bon?"

str.scan /\p{Alpha}{4,}/
  #=> ["asked", "stork", "soup", "Très"]

The regular expression reads, "Match strings containing 4 or more letters". I've used \p{Alpha} (same as \p{L} and [[:alpha:]]) to match unicode letters. (These are documented in Regexp. Search for these expressions there.) You could replace \p{Alpha} with [a-zA-Z], but in that case "Très" would not be matched.

If you wish to also match digits, use \p{Alnum} or [[:alnum:]] instead. While \w also matches letters (English only) and digits, it also matches underscores, which you probably don't want in this situation.

Punctuation can be a problem when words are extracted from the string by splitting on whitespace.

arr = "That   is a cow.".split
  #=> ["That", "is", "a", "cow."]
arr.select { |word| word.size >= 4 }
  #=> ["That", "cow."]

but "cow" has only three letters. If you instead used String#scan to extract words from the string you obtain the desired result.

arr = "That   is a cow?".scan /\p{Alpha}+/
  #=> ["That", "is", "a", "cow"]
arr.select { |word| word.size >= 4 }
  #=> ["That"]

However, if you use scan you may as well use a regular expression to retrieve only words having at least 4 characters, and skip the extra step.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.