From: Matthew Moss Date: 2008-07-19T01:03:08+09:00 Subject: [QUIZ] Records and Arrays (#170) -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 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 . 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 -- Matthew Moss