开发者

Convert array of hashes to array of structs?

Let's say I have two objects: User and Race.

class User
  attr_accessor :first_name
  attr_accessor :last_name
end

class Race
  attr_accessor :course
  attr_accessor :start_time
  attr_accessor :end_time
end

Now let's say I create an array of hashes like this:

user_races = races.map{ |race| {:user => race.user, :race => race} }

How do I then convert user_races into an array of structs, keeping in mind that I want to be able to access the attributes of both user and race fro开发者_StackOverflowm the struct element? (The key thing is I want to create a new object via Struct so that I can access the combined attributes of User and Race. For example, UserRace.name, UserRace.start_time.)


Try this:

class User
  attr_accessor :first_name
  attr_accessor :last_name
end

class Race
  attr_accessor :course
  attr_accessor :start_time
  attr_accessor :end_time
end

UserRace = Struct.new(:first_name, :last_name, :course, :start_time, :end_time)

def get_user_race_info      
  user_races = races.map do |r| 
    UserRace.new(r.user.first_name, r.user.last_name, 
              r.course, r.start_time, r.end_time)
  end
end

Now let's test the result:

user_races = get_user_race_info
user_races[0].first_name
user_races[0].end_time


Create a definition for the UserRace object (as a Struct), then just make an array of said objects.

UserRace = Struct.new(:user, :race)

user_races = races.map { |race| UserRace.new(race.user, race) }

# ...

user_races.each do |user_race|
  puts user_race.user
  puts user_race.race
end


if your hash has so many attributes such that listing them all:

user_races = races.map{ |race| {:user => race.user, :race => race, :best_lap_time => 552.33, :total_race_time => 1586.11, :ambient_temperature => 26.3, :winning_position => 2, :number_of_competitors => 8, :price_of_tea_in_china => 0.38 } } # garbage to show a user_race hash with many attributes

becomes cumbersome (or if you may be adding more attributes later), you can use the * ("splat") operator.

the splat operator converts an array into an argument list. so you can populate Struct.new's argument list with the list of keys in your hash by doing:

UserRace = Struct.new(*races.first.keys)

of course, this assumes all hashes in your array have the same keys (in the same order).

once you have your struct defined, you can use inject to build the final array of objects. (inject greatly simplifies converting many objects from one data type to another.)

user_races.inject([]) { |result, user_race| result << UserRace.new(*user_race.values) }


You have this :::

user_races = races.map{ |race| {:user => race.user, :race => race} }

Now create a Struct as shown below :

UserRace = Struct.new(:user, :race)

And then ::

user_races.each do |user_race|
   new_array << UserRace.new(user_race[:user],user_race[:race])
end

Haven't tested the code... should be fine... what say?

EDIT: Here I am adding the objects of UserRace to a new_array.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜