Rails数组group_by

时间:2015-11-30 03:51:49

标签: ruby-on-rails arrays ruby

我有一个来自数据库查询的动态数组对象结果。

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

查询:

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)

如何按用户对此进行分组,结果如下:

final_array = {
  "USER1" => [[3,4],[9,2],[3,1]], 
  "USER2" => [[0,4],[9,2],[9,1]],
  "USER3" => [[0,4],[8,2],[8,1]]
}

我尝试在rails中使用group_by,但结果与我想要的结果不一样。任何人都可以帮我一把吗?感谢。

3 个答案:

答案 0 :(得分:3)

假设objects是包含anonymous_user_idchoice_indexlegend属性的ActiveModel对象的可枚举对象,这将执行您想要的操作:

objects.map {|obj| obj.values_at(:anonymous_user_id, :choice_index, :legend) }
  .group_by(&:shift)

如果您在ActiveRecord查询中使用map,则可以跳过pluck,例如:

MyModel.where(...)
  .pluck(:anonymous_user_id, :choice_index, :legend)
  .group_by(&:shift)

修改

在回复你的评论时,是的,虽然它不是那么干净:

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__") }

或者:

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

答案 1 :(得分:1)

假设查询的结果是data_hash(哈希数组),那么以下内容将为您提供所需的结果:

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]]}

答案 2 :(得分:1)

我不相信有 rails方式来做这件事,但是你可以用红宝石

# 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] }