合并基于外键的两个数组(Merge two arrays based on Foreign Keys)

我有一个搜索功能,它查找两个模型A和B 结果是@a和@b 。 两者都包含manufacturer_id和model_id :

@a = [ #<A id: 6, manufacturer_id: 1, model_id: 6, front: 30, side: 39, rear: 19, roof: 0, created_at: "2016-12-17 23:34:58", updated_at: "2016-12-17 23:34:58">, #<A id: 10, manufacturer_id: 1, model_id: 10, front: 30, side: 39, rear: 19, roof: 0, created_at: "2016-12-17 23:34:58", updated_at: "2016-12-17 23:34:58"> ] @b = [ #<B id: 167, manufacturer_id: 1, model_id: 6, FL_1: 30, FL_2: 24, FR_1: 30, FR_2: 24, FC_1: 0, FC_2: 0, RL_1: 22, RL_2: 24, RR_1: 22, RR_2: 24, RC_1: 20, RC_2: 11, third_1: 0, third_2: 0, forth_1: 0, forth_2: 0, boot_1: 0, boot_2: 0, total: 60, created_at: "2016-12-17 23:35:10", updated_at: "2016-12-17 23:35:10">, #<B id: 175, manufacturer_id: 1, model_id: 10, FL_1: 28, FL_2: 22, FR_1: 28, FR_2: 22, FC_1: 0, FC_2: 0, RL_1: 26, RL_2: 22, RR_1: 26, RR_2: 22, RC_1: 12, RC_2: 18, third_1: 0, third_2: 0, forth_1: 0, forth_2: 0, boot_1: 0, boot_2: 0, total: 44, created_at: "2016-12-17 23:35:10", updated_at: "2016-12-17 23:35:10"> ]

我试图根据他们的manufacturer_id和model_id合并两个数组。 预期的结果是:

@output = [#<A id: 6, B id: 167, manufacturer_id: 1, model_id: 6>], #<A id: 10, B id: 175, manufacturer_id: 1, model_id: 10>]

在我看来,我的结果应该仍然能够参考manufacturer和model模型并获得具体参数。

<% @output.each do |r| %> <tr> <td><%= r.manufacturer.name %></td> <td><%= link_to r.model.name, edit_model_path(r) %></td> <td colspan=2> <%= link_to "View", a_path(r), class: "button btn btn-success btn-xs" %> <%= link_to "Edit", edit_b_path(r), class: "button btn btn-warning btn-xs" %> </td> <td colspan=2> <%= link_to "View", b_path(r), class: "button btn btn-success btn-xs" %> <%= link_to "Edit", edit_b_path(r), class: "button btn btn-warning btn-xs" %> </td> </tr> <% end %>

我发现我可以使用id加入他们两个。 但是,我不知道如何根据它们的common / foreign key id加入它们。

我试过这个,但它没有做到这一点:

outputs = (@a+@b).group_by{|h| h[:manufacturer_id]}.map{|k,v| v.reduce(:merge)}

请指导我。

I have a search function, which looks up two models A and B. The results are @a and @b. Both consist of manufacturer_id and model_id:

@a = [ #<A id: 6, manufacturer_id: 1, model_id: 6, front: 30, side: 39, rear: 19, roof: 0, created_at: "2016-12-17 23:34:58", updated_at: "2016-12-17 23:34:58">, #<A id: 10, manufacturer_id: 1, model_id: 10, front: 30, side: 39, rear: 19, roof: 0, created_at: "2016-12-17 23:34:58", updated_at: "2016-12-17 23:34:58"> ] @b = [ #<B id: 167, manufacturer_id: 1, model_id: 6, FL_1: 30, FL_2: 24, FR_1: 30, FR_2: 24, FC_1: 0, FC_2: 0, RL_1: 22, RL_2: 24, RR_1: 22, RR_2: 24, RC_1: 20, RC_2: 11, third_1: 0, third_2: 0, forth_1: 0, forth_2: 0, boot_1: 0, boot_2: 0, total: 60, created_at: "2016-12-17 23:35:10", updated_at: "2016-12-17 23:35:10">, #<B id: 175, manufacturer_id: 1, model_id: 10, FL_1: 28, FL_2: 22, FR_1: 28, FR_2: 22, FC_1: 0, FC_2: 0, RL_1: 26, RL_2: 22, RR_1: 26, RR_2: 22, RC_1: 12, RC_2: 18, third_1: 0, third_2: 0, forth_1: 0, forth_2: 0, boot_1: 0, boot_2: 0, total: 44, created_at: "2016-12-17 23:35:10", updated_at: "2016-12-17 23:35:10"> ]

I am trying to merge the two arrays based on their manufacturer_id and model_id. The expected result is:

@output = [#<A id: 6, B id: 167, manufacturer_id: 1, model_id: 6>], #<A id: 10, B id: 175, manufacturer_id: 1, model_id: 10>]

In my view, my result should still be able to refer to manufacturer and model models and obtain the specific parameter.

<% @output.each do |r| %> <tr> <td><%= r.manufacturer.name %></td> <td><%= link_to r.model.name, edit_model_path(r) %></td> <td colspan=2> <%= link_to "View", a_path(r), class: "button btn btn-success btn-xs" %> <%= link_to "Edit", edit_b_path(r), class: "button btn btn-warning btn-xs" %> </td> <td colspan=2> <%= link_to "View", b_path(r), class: "button btn btn-success btn-xs" %> <%= link_to "Edit", edit_b_path(r), class: "button btn btn-warning btn-xs" %> </td> </tr> <% end %>

I found out that I can join both of them using id. However, I have no clue how to join them based on their common/foreign key id.

I tried this, but it did not do the job:

outputs = (@a+@b).group_by{|h| h[:manufacturer_id]}.map{|k,v| v.reduce(:merge)}

Please guide me.

最满意答案

您可以使用group_by和set intersection来查找具有公共ID的对象。

更新:现在使用set union,输出每个id组合。

@a = [ { id: 6, manufacturer_id: 1, model_id: 6 }, { id: 10, manufacturer_id: 1, model_id: 10 }, { id: 111, manufacturer_id: 3, model_id: 4 } ] @b = [ { id: 167, manufacturer_id: 1, model_id: 6 }, { id: 175, manufacturer_id: 1, model_id: 10 }, { id: 176, manufacturer_id: 2, model_id: 3 } ] def group_by_ids(array) array.group_by { |h| h.values_at(:manufacturer_id, :model_id) } end a_by_ids = group_by_ids(@a) b_by_ids = group_by_ids(@b) common_keys = a_by_ids.keys & b_by_ids.keys all_keys = a_by_ids.keys | b_by_ids.keys result = all_keys.map do |ids| a_objects = a_by_ids[ids] b_objects = b_by_ids[ids] a_object = a_objects && a_objects.first b_object = b_objects && b_objects.first [*ids, a_object, b_object] end

它输出:

[[1, 6, {:id=>6, :manufacturer_id=>1, :model_id=>6}, {:id=>167, :manufacturer_id=>1, :model_id=>6}], [1, 10, {:id=>10, :manufacturer_id=>1, :model_id=>10}, {:id=>175, :manufacturer_id=>1, :model_id=>10}], [3, 4, {:id=>111, :manufacturer_id=>3, :model_id=>4}, nil], [2, 3, nil, {:id=>176, :manufacturer_id=>2, :model_id=>3}]]

所以你得到一个数组数组,每个子数组看起来像:

[manufacturer_id, model_id, a_object, b_object]

您可能需要稍微调整一下视图,但每个数组中应该有足够的信息。

You can use group_by and set intersection to find the objects with common ids.

Update : set union is now used, to output every id combination.

@a = [ { id: 6, manufacturer_id: 1, model_id: 6 }, { id: 10, manufacturer_id: 1, model_id: 10 }, { id: 111, manufacturer_id: 3, model_id: 4 } ] @b = [ { id: 167, manufacturer_id: 1, model_id: 6 }, { id: 175, manufacturer_id: 1, model_id: 10 }, { id: 176, manufacturer_id: 2, model_id: 3 } ] def group_by_ids(array) array.group_by { |h| h.values_at(:manufacturer_id, :model_id) } end a_by_ids = group_by_ids(@a) b_by_ids = group_by_ids(@b) common_keys = a_by_ids.keys & b_by_ids.keys all_keys = a_by_ids.keys | b_by_ids.keys result = all_keys.map do |ids| a_objects = a_by_ids[ids] b_objects = b_by_ids[ids] a_object = a_objects && a_objects.first b_object = b_objects && b_objects.first [*ids, a_object, b_object] end

It outputs :

[[1, 6, {:id=>6, :manufacturer_id=>1, :model_id=>6}, {:id=>167, :manufacturer_id=>1, :model_id=>6}], [1, 10, {:id=>10, :manufacturer_id=>1, :model_id=>10}, {:id=>175, :manufacturer_id=>1, :model_id=>10}], [3, 4, {:id=>111, :manufacturer_id=>3, :model_id=>4}, nil], [2, 3, nil, {:id=>176, :manufacturer_id=>2, :model_id=>3}]]

So you get an array of arrays, where each sub-array looks like :

[manufacturer_id, model_id, a_object, b_object]

You might need to adapt your views a bit, but you should have enough information in each array.

更多推荐