Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rotate by 90° an Array with ActiveRecord objects

I have got

@my_objects = [ #<MyObject id: 1, title: "Blah1">,
                #<MyObject id: 2, title: "Blah2">,
                #<MyObject id: 3, title: "Blah3">,
                #<MyObject id: 4, title: "Blah4"> ]

I need to turn it into:

@my_objects = { :id => [ 1, 2, 3, 4],
                :title => [ "Blah1" ... ] }

Is there built in method or some standart approach?

I can imagine only this

@my_objects.inject({}){ |h, c| c.attributes.each{ |k,v| h[k] ||= []; h[k] << v }; h }

This question was born while I was thinking on this particular question

like image 237
fl00r Avatar asked Apr 25 '26 19:04

fl00r


2 Answers

First, use Enumerable#map (something like @o.map { |e| [e.id, e.title] }) to get the ActiveRecord array into a simplified pure Ruby object that looks like this:

a = [[1, "Blah1"], [2, "Blah2"], [3, "Blah3"], [4, "Blah4"]]

Then:

a.transpose.zip([:id, :title]).inject({}) { |m, (v,k)| m[k] = v; m }

Alternate solution: It might be less tricky and easier to read if instead you just did something prosaic like:

i, t = a.transpose
{ :id => i, :title => t }

Either way you get:

 => {:title=>["Blah1", "Blah2", "Blah3", "Blah4"], :id=>[1, 2, 3, 4]} 

Update: Tokland has a refinement that's worth citing:

Hash[[:id, :title].zip(a.transpose)]
like image 76
DigitalRoss Avatar answered Apr 27 '26 09:04

DigitalRoss


You're on the right track there, there's no custom method for this sort of pivot, and it should work, but remember that ActiveRecord attribute keys are strings:

@my_objects.inject({ }) { |h, c| c.attributes.each { |k,v| (h[k.to_sym] ||= [ ]) << v }; h }

You can use the (x ||= [ ]) << y pattern to simplify that a bit if you're not too concerned with it being super readable to a novice.

like image 45
tadman Avatar answered Apr 27 '26 10:04

tadman