Matthew Moss ha scritto:
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
>
> The three rules of Ruby Quiz 2:
>
> 1.  Please do not post any solutions or spoiler discussion for this
> quiz until 48 hours have passed from the time on this message.
>
> 2.  Support Ruby Quiz 2 by submitting ideas as often as you can! (A
> permanent, new website is in the works for Ruby Quiz 2. Until then,
> please visit the temporary website at
>
>      <http://splatbang.com/rubyquiz/>.
>
> 3.  Enjoy!
>
> Suggestion:  A [QUIZ] in the subject of emails about the problem
> helps everyone on Ruby Talk follow the discussion.  Please reply to
> the original quiz message, if you can.
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
>
> ## Records and Arrays (#170)
>
> In a typical application, you might use what is commonly referred to
> as an "array of records." Essentially, this is a single array
> containing multiple objects that represent the same kind of structured
> data, either as defined class or OpenStruct instances. Take, for
> example, this bit of code that reads in some data regarding people:
> their names, ages and favorite colors.
>
>     require 'ostruct'
>     data = []
>     File.open("data.txt").each do |line|
>       name, age, color = line.chomp.split(/,/)
>       d = OpenStruct.new
>       d.name = name
>       d.age = age
>       d.color = color
>       data << d
>     end
>
> The variable `records` is considered an "array of records", since to
> get any particular piece of data, you must first access it as an array
> (to get a particular record), then access it as a record (to get a
> particular field).
>
>     > p data[3].name
>     => "Matthew"
>
>     > p data[3].age
>     => 36
>
> However, at times, it is more convenient to store data as a "record of
> arrays". Instead of one array containing multiple records, you have
> one object (i.e. record) containing multiple, parallel arrays. Access
> to data then is done first as a record, then as an array.
>
>     > p data.name[3]
>     => "Matthew"
>
>     > p data.age[3]
>     => 36
>
> This sort of arrangement is useful when you want to access series of
> data at a time. For example, if I have a graphing component that takes
> two arrays -- one for the domain axis, and another for the range axis
> -- a "record of arrays" will make accessing that data trivial.
>
> *Your task this week* is to define two functions that move data
> between "array of records" storage and "record of arrays" storage.
>
>     def aor_to_roa(arr)
>       # This method accepts an array of records, and
>       # should return a single record of arrays.
>       #
>       # This is your task!
>     end
>
>     def roa_to_aor(rec)
>       # This method accepts a record of arrays, and
>       # should return a single array of records.
>       #
>       # This is also your task!
>     end
>
> You should make this work with [OpenStruct][1]; do not limit yourself
> to the example records shown above.
>
> There are two, optional extra-credits for this week.
>
> 1. Extend these two functions to accept arbitrary classes.
>
> 2. As an alternative to these two functions, create an adapter class
> that can wrap around "array of records" data to provide a "record of
> arrays" interface without actually moving data about.
>
>
> [1]: http://www.ruby-doc.org/stdlib/libdoc/ostruct/rdoc/classes/OpenStruct.html
>
>
>
>   
Hi all,

here's my solution:

require 'ostruct'

def aor_to_roa(arr)
  hash = { }
  arr.each do |record|
    record.marshal_dump.each_key { |field| (hash[field] ||= []) << 
record.send(field) }
  end
  OpenStruct.new(hash)
end

def roa_to_aor(rec)
  result = []
  rec.marshal_dump.each do |field, array|
    array.each_with_index { |value, index| (result[index] ||= 
OpenStruct.new).send("#{field}=", value) }
  end
  result
end