简体   繁体   English

在Rails中,将哈希压缩为嵌套哈希的最佳方法是什么

[英]In Rails, what is the best way to compact a hash into a nested hash

Say I have this: 说我有这个:

[
  { :user_id => 1, :search_id => a},
  { :user_id => 1, :search_id => b},
  { :user_id => 2, :search_id => c},
  { :user_id => 2, :search_id => d}
]

and I want to end up with: 我想最终得到:

[
  { :user_id => 1, :search_id => [a,b]},
  { :user_id => 2, :search_id => [c,d]}
]

What is the best way to do that? 最好的方法是什么?

Very strange requirement indeed. 确实非常奇怪的要求。 Anyway 无论如何

[ { :user_id => 1, :search_id => "a"},
  { :user_id => 1, :search_id => "b"},
  { :user_id => 2, :search_id => "c"},
  { :user_id => 2, :search_id => "d"} ] \
    .map{ |h| h.values_at(:user_id, :search_id) } \
    .group_by(&:first) \
    .map{ |k, v| { :user_id => k, :search_id => v.map(&:last) } }
array.group_by{|x| x[:user_id] }.values.map do |val|
  { user_id:   val.first[:user_id], 
    search_id: val.inject([]){|me, el| me << el[:search_id]} }
end

First off, I think the cleaner output structure here is to allow the user IDs to be the hash keys and the list of search IDs to be the values: 首先,我认为这里更清晰的输出结构是允许用户ID为散列键,搜索ID列表为值:

{
  1 => [a, b],
  2 => [c, d]
}

There might be a clever way using Rails helpers to get this structure, but it's not too bad to do it manually, either: 使用Rails助手可能有一种聪明的方法来获得这种结构,但手动执行它并不是太糟糕:

output = {}
input.each do |row|
  key = row[:user_id]
  value = row[:search_id]

  output[key] ||= []
  output[key] << value
end

I agree with Matchus representation of the data and just want to suggest a shorter version for it (input being the initial array). 我同意Matchus对数据的表示,并且只想为它建议一个更短的版本(输入是初始数组)。

input.each.with_object(Hash.new {|h,k| h[k] = []}) do |k,o|
  o[k[:user_id]] << k[:search_id]
end

EDIT: this is Ruby > 1.9 编辑:这是Ruby> 1.9

input.inject({}) do
  |m, h| (m[h[:user_id]] ||= []) << h[:search_id]; m
end.inject([]) { |m, (k, v)| m << { :user_id => k, :search_id => v }; m }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM