0

I am wondering how one would search through an array of hashes and return a value based on a search string. For example, @contacts contains the hash elements: :full_name, :city, and :email. The variable @contacts (I guess it would be an array) contains three entries (perhaps rows). Below is the code I have so far to conduct a search based on :city value. However it's not working. Can anyone give me an idea what's going on?

def search string
  @contacts.map {|hash| hash[:city] == string}
end

2 Answers 2

2

You should use select instead of map:

def search string
  @contacts.select { |hash| hash[:city] == string }
end

In your code you tried to map (or transform) your array using a block, which yields boolean values. map takes a block and invokes the block for each element of self, constructing a new array containing elements returned by the block. As the result, you got an array of booleans.

select works similar. It takes a block and iterates over the array as well, but instead of transforming the source array it returns an array containing elements for which the block returns true. So it's a selection (or filtering) method.

In order to understand the difference between these two methods it's useful to see their example definitions:

class Array
  def my_map
    [].tap do |result|
      self.each do |item|
        result << (yield item)
      end
    end
  end

  def my_select
    [].tap do |result|
      self.each do |item|
        result << item if yield item
      end
    end
  end
end

Example usage:

irb(main):007:0> [1,2,3].my_map { |x| x + 1 }
[2, 3, 4]
irb(main):008:0> [1,2,3].my_select { |x| x % 2 == 1 }
[1, 3]
irb(main):009:0>
Sign up to request clarification or add additional context in comments.

2 Comments

This worked. In your answer though, does this syntax basically tell the program to separate each element for inspection: { |hash| hash[:city] == string }
@NealR, yes this is a syntax for a block, i.e. a piece of code which is invoked for each item of the array (in case of passing the block to select). The resulting array will contain only those items, for which the block holds true.
1

You can try this:

 def search string
    @contacts.select{|hash| h[:city].eql?(string) }
 end

This will return an array of hashes which matches string.

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.