Reputation: 905
I have a dynamic array of object result from a database query.
USERNAME choice_indx legend
USER1 3 4
USER2 0 4
USER3 0 4
USER1 9 2
USER2 9 2
USER3 8 2
USER1 3 1
USER2 9 1
USER3 8 1
Query:
SELECT survey_answers.anonymous_user_id, survey_answers.choice_index, survey_questions.legend
FROM `survey_answers`
LEFT JOIN surveys ON surveys.id = survey_answers.survey_id
LEFT JOIN survey_questions ON survey_questions.id = survey_answers.survey_question_id
WHERE (survey_questions.legend IN (1,2,4)) AND (survey_answers.track_id =2) AND (survey_answers.survey_id =2) AND (surveys.survey_type =2)
How can I group this by user and result it like this:
final_array = {
"USER1" => [[3,4],[9,2],[3,1]],
"USER2" => [[0,4],[9,2],[9,1]],
"USER3" => [[0,4],[8,2],[8,1]]
}
I've tried using group_by in rails, but the result was not the same from what I want. Can anyone lend me a hand? Thanks.
Upvotes: 3
Views: 7874
Reputation: 106027
Assuming objects
is an Enumerable of ActiveModel objects with anonymous_user_id
, choice_index
, and legend
attributes, this will do what you want:
objects.map {|obj| obj.values_at(:anonymous_user_id, :choice_index, :legend) }
.group_by(&:shift)
You can skip the map
if instead you use pluck
in your ActiveRecord query, e.g.:
MyModel.where(...)
.pluck(:anonymous_user_id, :choice_index, :legend)
.group_by(&:shift)
In reply to your comment, yes it is, although it's not quite as clean:
MyModel.where(...)
.pluck(:anonymous_user_id, :choice_index, :legend)
.map {|vals| Hash[ %w[ __key__ c_idx legend ].zip(vals) ] }
.group_by {|hsh| hsh.delete("__key__") }
Or:
MyModel.where(...)
.pluck(:anonymous_user_id, :choice_index, :legend)
.each_with_object(Hash.new {|h,k| h[k] = [] }) do |(key, c_idx, legend), hsh|
hsh[key] << { "c_idx" => c_idx, "legend" => legend }
end
Upvotes: 3
Reputation: 34318
Assuming the result from the query is data_hash
(array of hash), then the following will give you the desired result:
data_hash = [{ 'USERNAME' => 'USER1', 'choice_indx' => 3, 'legend' => 4 },
{ 'USERNAME' => 'USER2', 'choice_indx' => 0, 'legend' => 4 },
{ 'USERNAME' => 'USER3', 'choice_indx' => 0, 'legend' => 4 },
{ 'USERNAME' => 'USER1', 'choice_indx' => 9, 'legend' => 2 },
{ 'USERNAME' => 'USER2', 'choice_indx' => 9, 'legend' => 2 },
{ 'USERNAME' => 'USER3', 'choice_indx' => 8, 'legend' => 2 },
{ 'USERNAME' => 'USER1', 'choice_indx' => 3, 'legend' => 1 },
{ 'USERNAME' => 'USER2', 'choice_indx' => 9, 'legend' => 1 },
{ 'USERNAME' => 'USER3', 'choice_indx' => 8, 'legend' => 1 }]
final_array = Hash.new{|h,k|h[k]=[]}
data_hash.each do |data|
final_array[data['USERNAME']] << [data['choice_indx'], data['legend']]
end
p final_array
# => {"USER1"=>[[3, 4], [9, 2], [3, 1]], "USER2"=>[[0, 4], [9, 2], [9, 1]], "USER3"=>[[0, 4], [8, 2], [8, 1]]}
Upvotes: 1
Reputation: 4526
I don't believe there is a rails way to do this, but with ruby you could do
# create hash with a empty array for each username
results = Hash[@query.pluck(:username).map { |username| [username, []] }]
@query.each { |data| results[data.username] << [data.choice_idx,
data.legend] }
Upvotes: 1