Как повернуть массив на 90 ° с объектами ActiveRecord - PullRequest
3 голосов
/ 09 мая 2011

у меня есть

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

Мне нужно превратить это в:

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

Есть ли встроенный метод или какой-то стандартный подход?

Я могу представить только это

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

Этот вопрос родился, когда я размышлял над этим конкретным вопросом

Ответы [ 3 ]

5 голосов
/ 09 мая 2011

Во-первых, используйте Enumerable # map (что-то вроде @o.map { |e| [e.id, e.title] }), чтобы получить массив ActiveRecord в упрощенный чистый объект Ruby, который выглядит следующим образом:

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

Тогда:

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

Альтернативное решение: Это может быть менее сложно и проще для чтения, если вместо вместо вы только что сделали что-то прозаическое:

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

В любом случае вы получите:

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

Обновление: Tokland имеет уточнение, на которое стоит ссылаться:

Hash[[:id, :title].zip(a.transpose)]
2 голосов
/ 09 мая 2011

Функциональный подход (не каждый!):

pairs = @my_objects.map { |obj| obj.attributes.to_a }.flatten(1)   
Hash[pairs.group_by(&:first).map { |k, vs| [k, vs.map(&:second)] }]
#=> {:title=>["Blah1", "Blah2", "Blah3", "Blah4"], :id=>[1, 2, 3, 4]}

Как обычно, Facets позволяет писать более приятный код; в этом случае Enumerable#map_by позволит избежать использования уродливого и запутанного шаблона group_by + map + map:

@my_objects.map { |obj| obj.attributes.to_a }.flatten(1).map_by { |k, v| [k, v] }   
#=> {:title=>["Blah1", "Blah2", "Blah3", "Blah4"], :id=>[1, 2, 3, 4]}
2 голосов
/ 09 мая 2011

Вы находитесь на правильном пути, нет никакого специального метода для такого типа сводки, и он должен работать, но помните, что ключи атрибута ActiveRecord являются строками:

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

Вы можете использовать шаблон (x ||= [ ]) << y, чтобы немного упростить его, если вы не слишком заинтересованы в том, чтобы он был суперчитаемым для новичка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...