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

6

假设我有以下内容:

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

我希望最终得到:

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

什么是最好的方法呢?
5个回答

7

确实是一个非常奇怪的需求。无论如何,

[ { :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) } }

1
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

0
首先,我认为更清晰的输出结构是允许用户ID成为哈希键,搜索ID列表成为值:
{
  1 => [a, b],
  2 => [c, d]
}

也许使用Rails助手有一种聪明的方法来获取这个结构,但是手动完成也不太难:

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

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

0

我同意Matchus对数据的表示,并建议一个更简短的版本(输入为初始数组)。

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

编辑:这是 Ruby > 1.9


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接