Ruby数组有Hash对吗?

时间:2014-12-04 05:32:55

标签: ruby-on-rails ruby ruby-on-rails-3

我有如下的ruby数组:

array = [{"id"=>8, "book_id"=>14238}, {"id"=>5, "book_id"=>14238}, {"id"=>7, "book_id"=>10743}, {"id"=>9, "book_id"=>10743}]

我想要一个新的数组,结合ids具有相同book_id的结果。

预期结果

array = [{"book_id"=>14238, "id"=>[8,5]}, {"book_id"=>10743, "id"=>[7,9]}]

3 个答案:

答案 0 :(得分:2)

我不能说这很容易理解,但它很简洁:

array.group_by {|item| item["book_id"] }.map do |k, v|
  { "book_id" => k, "id" => v.map {|item| item["id"] } }
end

=> [{"book_id"=>14238, "id"=>[8, 5]}, {"book_id"=>10743, "id"=>[7, 9]}]

group_by完成的第一次转化会重新排列您的数组,以便将具有相同book_id的项目组合在一起:

array.group_by {|item| item["book_id"] }
 => {14238=>[{"id"=>8, "book_id"=>14238}, {"id"=>5, "book_id"=>14238}], 10743=>[{"id"=>7, "book_id"=>10743}, {"id"=>9, "book_id"=>10743}]}

第二个转换(map)将group_by生成的哈希重新格式化为哈希列表,第二个map将id收集到列表中。

答案 1 :(得分:1)

您也可以使用Hash#update(a.k.a。merge!)的形式执行此操作,该格式使用块来解析合并后的两个哈希中包含的键的值。

<强>代码

def aggregate(arr)
  arr.each_with_object({}) do |g,h|
    f = { g["book_id"]=>{ "id"=>[g["id"]], "book_id"=>g["book_id"] } }
    h.update(f) do |_,ov,nv|
      ov["id"] << nv["id"].first
      ov
    end
  end.values
end

示例

arr = [{"id"=>8, "book_id"=>14238}, {"id"=>5, "book_id"=>14238},
       {"id"=>7, "book_id"=>10743}, {"id"=>9, "book_id"=>10743},
       {"id"=>6, "book_id"=>10511}]

aggregate(arr)
  #=> [{"id"=>[8, 5], "book_id"=>14238},
  #    {"id"=>[7, 9], "book_id"=>10743},
  #    {"id"=>[6],    "book_id"=>10511}]

替代输出

根据您的要求,您可以考虑构建单个哈希而不是另一个哈希数组:

def aggregate(arr)
  arr.each_with_object({}) { |g,h|
    h.update({ g["book_id"]=>[g["id"]] }) { |_,ov,nv| ov+nv } }
end

aggregate(arr)
  #=> {14238=>[8, 5], 10743=>[7, 9], 10511=>[6]}

答案 2 :(得分:0)

我为输出使用哈希以便于查找和/或重用:

array = [{"id"=>8, "book_id"=>14238}, {"id"=>5, "book_id"=>14238}, {"id"=>7, "book_id"=>10743}, {"id"=>9, "book_id"=>10743}]

hash = array.group_by{ |h| h['book_id'] }.map{ |k, v| [k, v.flat_map{ |h| h['id'] }]}.to_h
# => {14238=>[8, 5], 10743=>[7, 9]}

键是book_id值,关联的数组包含id值。


的预期结果
array = [{"book_id"=>14238, "id"=>[8,5]}, {"book_id"=>10743, "id"=>[7,9]}]
如果你要在其中进行任何类型的查找,

不是一个好的结构。想象一下,有数百或数千个元素需要在数组中找到"book_id" == 10743,特别是如果它不是一个排序列表;必须走这个数组,直到找到所需的条目。这是一个缓慢的过程。

相反,将结构简化为简单的哈希,允许您使用简单的哈希查找轻松找到值:

hash[10743]

查找永远不会减慢。

如果要通过排序按顺序迭代结果数据,请使用

sorted_keys = hash.keys.sort

hash.values_at(*sorted_keys)

以排序顺序提取值。如果需要提取键/值,则迭代哈希,也许是为了插入数据库。