0

I'm new to learning Ruby and am having a little trouble with nested structures.

What I'm trying to do is return :last name ("Doe") if the value of :first is "John":

people = {
  :family => [
    {:first => "John", :last => "Doe"},
    {:first => "Jane", :last => "Smith"}
  ]
}

people[:family].each {|index| return index[:last] if index[:first] == "John"}

However, the console is giving me this error:

test.rb:8:in `block in <main>': unexpected return (LocalJumpError)
from test.rb:8:in `each'
from test.rb:8:in `<main>'

When I test this in the console and replace 'return' with 'puts', it gives me back "Doe" but for some reason the 'return' seems to be causing the 'unexpected return (LocalJumpError)'. How can I successfully return this value without running into this error?

Thanks - any and all help is greatly appreciated!

dace
  • 5,819
  • 13
  • 44
  • 74
  • 1
    You're returning inside the `.each`, which isn't the same as returning from a method (hence, unexpected). You want [`.select{}`](http://ruby-doc.org/core-2.2.1/Enumerable.html#method-i-select) – Jon Egeland Mar 07 '15 at 17:04

4 Answers4

1

Use break with value

people = {
  :family => [
    {:first => "John", :last => "Doe"},
    {:first => "Jane", :last => "Smith"}
  ]
}

people[:family].each {|index| break index[:last] if index[:first] == "John"}
Anton Harniakou
  • 855
  • 6
  • 13
1

You can't use return within an each loop. You could use map or collect to return an array of last names like so:

people[:family].collect {|index| index[:last] if index[:first] == "John"}
=> ["Doe", nil]

You could also push your matches to an output variables like so:

output = []
people[:family].each {|index| output << index[:last] if index[:first] == "John"}
=> ["Doe"]

Using break as was suggested, will return a string of the first match, but if you have more than one match, it will not work for you. See example below:

people = {
  :family => [
    {:first => "John", :last => "Doe"},
    {:first => "Jane", :last => "Smith"},
    {:first => "John", :last => "Galt"}
  ]
}
people[:family].each {|index| break index[:last] if index[:first] == "John"}
=> "Doe"
Daniel Bonnell
  • 4,817
  • 9
  • 48
  • 88
0

return needs to be used inside a method:

def foo
  # your code
end

foo # => "Doe"
August
  • 12,410
  • 3
  • 35
  • 51
0
puts people[:family].find({}) {|index| index[:first] == "John"}[:last]
Maxim
  • 9,701
  • 5
  • 60
  • 108