dpg5000
dpg5000

Reputation: 363

Returning index with value while using each_with_index method

Constructing a basic address book in Ruby. I have the following line of code in my program that iterates over the existing array(@address_book) based on a standard numeric input (entrynumber) to match the array index. The resulting value that matches that index is then returned. Here's the code in question:

     puts @address_book.entries.each_with_index.select {|val, i| i == (entrynumber - 1)}

the results look great except that the index is also returned at the bottom, like this: (note 0 at the end of return) I'd ideally like the index number itself at the bottom not returned.

View by Entry Number
Entry Number: 1
You picked 1
Name: adam adams
Phone Number: 111-111-1111
Email: [email protected]
0

What am I missing in terms of returning the value, but without the index?

Upvotes: 1

Views: 2123

Answers (2)

Kyle Decot
Kyle Decot

Reputation: 20815

It seems like what you want it to get a single item which isn't really what select is best suited for (especially when you're retrieving it via an index. I would probably do something like:

@address_book.entries.to_a[entrynumber - 1]

Upvotes: 0

Wayne Conrad
Wayne Conrad

Reputation: 107979

The problem

The trouble is that each_with_index is turning @address_book.entries into an array of arrays. Here's an example of what I mean:

["a", "b"].each_with_index.to_a
# => [["a", 0], ["b", 1]] 

So when you apply select to each_with_index, the selected elements are each going to be an array with the element and its index:

["a", "b"].each_with_index.select { |e, i| i == 1 }
=> [["b", 1]] 

A bad fix

You could fix that by using #map to select only the first element of each selected row:

["a", "b"].each_with_index.select { |e, i| i == 1 }.map(&:first)
 => ["b"] 

Using select.with_index

Better still, you could use select.with_index:

["a", "b"].select.with_index { |e, i| i == 1}
 => ["b"] 

Or, in the case of your code:

@address_book.entries.
  each_with_index.select.with_index {|val, i| i == (entrynumber - 1)}

Using Array#[]

If @address_book.entries is an array, then you can index the array, not using select at all:

@address_book_entries[entrynumber - 1]

If it's not an array, you can turn it into one with #to_a:

@address_book.entries.to_a[entrynumber - 1]

However, if @address_book.entries is large, this could use a lot of memory. Be careful when turning an enumeration into an array.

Upvotes: 2

Related Questions