2014-12-04 123 views
0

我有红宝石阵列如下:红宝石阵列有哈希对?

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

我想要一个新的阵列将具有相同的book_idids结果。

预期结果

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

回答

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到一个列表中。

+0

我复制我的解决方案,从IRB,在这里贴,我看到我的回答是完全按照你的+1 – Santhosh 2014-12-04 05:57:03

+0

我的答案是非常接近你一样'锡Man'我已删除BCZ很不满意预期产出。 1+ – 2014-12-04 06:00:11

+0

@Santosh:伟大的思想家一样思考! – 2014-12-04 06:04:35

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) 

在排序的顺序来提取的值。或者如果需要提取键/值,可能要插入到数据库中,则迭代散列。

+0

这不是预期的输出 – Santhosh 2014-12-04 05:54:55

+0

这是正确的。有时预期的输出不是处理数据的最佳方式。堆栈溢出不仅仅是返回预期的输出,还涉及到教育有更简单的方法来完成相同的结果。考虑如何轻松地预期输出可以被搜索或重用,而不是简单的哈希。预期的输出必须迭代才能找到特定的book_id,随着初始数组的增长,它会变得越来越慢。这几乎没有效率。 – 2014-12-04 05:56:41

1

您还可以使用Hash#update(也称为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]}