Ruby - Extract value of a particular key from array of hashes

11,256

Solution 1

As you've noticed, it's not very convenient to extract the name of user_id 7. You could modify your data structure a bit :

@profiles = [{:user_id=>5, :full_name=>"Emily Spot"},
             {:user_id=>7, :full_name=>"Kevin Walls"}]

@full_names = @profiles.each_with_object({}) do |profile, names|
  names[profile[:user_id]] = profile[:full_name]
end

p @full_names
# {5=>"Emily Spot", 7=>"Kevin Walls"}
p @full_names[7]
# "Kevin Walls"
p @full_names[6]
# nil

You didn't lose any information but name look-up is now much faster, easier and more robust.

Solution 2

@profiles is an array of hashes, with symbols as keys, whereas what you use is String objects.

So ':user_id' is a string, and you want symbol: :user_id:

@profiles.find{ |h| h[:user_id] == current_user.id } 

I want to get full_name of say user_id == 7

@profiles.find { |hash| hash[:user_id] == 7 }.fetch(:full_name, nil)

Note, I used Hash#fetch for case, when there is no hash with value 7 at key :user_id.

Solution 3

Suggesting, to create a new hash that can make things simpler

Eg:

results = {}
profiles = [
  {user_id: 5, full_name: "Emily Spot"},
  {user_id: 7, full_name: "Kevin Walls"}
]

profiles.each do |details|
  results[details[:user_id]] = details[:full_name]
end

Now, results will have:

{5: "Emily Spot", 7: "Kevin Walls"}

So, if you need to get full_name of say user_id = 7, simply do:

results[7] # will give "Kevin Walls"
Share:
11,256
Means
Author by

Means

I'm an entrepreneur, ex-Investment Banker and a mother of 2 lovely young kids aged 6 and 3 yrs old. I started a charity jobsite on Wordpress and wanted to have a full-featured website but could not find a tech co-founder. So, I attended Railsgirls London event in Nov 2016 and decided to plunge into making a jobsite all by myself on Ruby-on-Rails. I've never been a web developer and learnt it from other bloggers and the lovely Stackoverflow community. My husband was my motivation and lent occasional help especially during deployment. My first website is a full-featured social-media blogging engine where I write my own articles. Soon I'll also launch my job site in Rails. I want to inspire more women into Technology and it is definitely doable with SOhelp.

Updated on June 18, 2022

Comments

  • Means
    Means almost 2 years

    I have an array of hashes - @profiles which has data as:

    [{:user_id=>5, :full_name=>"Emily Spot"},{:user_id=>7, :full_name=>"Kevin Walls"}]
    

    I want to get full_name of say user_id = 7? I'm doing the following: but it's throwing an error that expression @profiles.find{|h| h[':user_id'] == current_user.id} is nil.

    name = @profiles.find{ |h| h[':user_id'] == current_user.id }[':full_name']
    

    if I use select instead of find then error is - no implicit conversion of String into Integer.

    How do I search through the array of hashes?

    UPDATE:

    After @Eric's answer, I restructured my job model & view actions:

      def full_names
        profile_arr||= []
        profile_arr = self.applications.pluck(:user_id)
        @profiles = Profile.where(:user_id => profile_arr).select([:user_id, :first_name, :last_name]).map {|e| {user_id: e.user_id, full_name: e.full_name} }
        @full_names = @profiles.each_with_object({}) do |profile, names|
          names[profile[:user_id]] = profile[:full_name]
        end
      end
    

    In the view....,

    p @current_job.full_names[current_user.id]