我有一个搜索功能,可以查找两个模型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
加入他们两个。但是,我不知道如何根据公共/外键id
加入它们。
我尝试了这个,但它没有做到这一点:
outputs = (@a+@b).group_by{|h| h[:manufacturer_id]}.map{|k,v| v.reduce(:merge)}
请指导我。
答案 0 :(得分:2)
您可以使用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]
您可能需要稍微调整一下视图,但每个数组中应该有足够的信息。
答案 1 :(得分:2)
这是另一种方法。
[@a, @b].flatten.group_by do |row|
row.values_at(:manufacturer_id, :model_id)
end.reduce([]) do |output, ((manufacturer_id, model_id), data)|
output << data.reduce({}) { |memo, x| memo.merge(x) }
end
如果您需要进行任何类型的重命名以防止哈希值发生冲突,您可以修改传递给data.reduce
的块以进行更细微的merge
。