2016-12-25 1 views
1

두 가지 모델 AB을 찾는 검색 기능이 있습니다. 결과는 @a@b입니다. 모두 manufacturer_idmodel_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_idmodel_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>] 

내 결과는 여전히 특정 매개 변수를 manufacturermodel 모델을 참조하여 획득 할 수 있어야한다.

<% @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 = (@[email protected]).group_by{|h| h[:manufacturer_id]}.map{|k,v| v.reduce(:merge)} 

이 나를 인도 해 주시기 바랍니다.

+0

a 및 b에 대한 올바른 예가 있습니까? 출력 결과는 무엇입니까? 루비 배열은'[]'사이에 있습니다. 또한 변수 또는 속성 이름을 사용하지 말고 Ruby 객체 (1, "model_x", ...)를 사용한 구체적인 예 –

+0

@EricDuminil 제안에 따라 실제 예제를 추가했습니다. 내가 사람들이 쉽게 볼 수 있도록 그 방식으로 넣고 싶었던 이유. 감사! –

+0

a는'A' 객체들의 배열이고, b는'B' 객체들의 배열이고, 당신은'manufacturer_id'와'model_id'에 의해 a와 b를 그룹화하기를 원합니까? –

답변

2

group_byset intersection을 사용하여 공통 ID가있는 개체를 찾을 수 있습니다.

업데이트 : 모든 유니언 조합을 출력하기 위해 이제 set union이 사용됩니다.

@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] 
당신은 귀하의 의견을 조금 적응해야 할 수도 있습니다

을, 각 배열에 충분한 정보가 있어야합니다.

+0

nil에 대해'undefined method 'group_by'오류가 발생했습니다 :이'array.group_by {| h | [h [: manufacturer_id], h [: model_id]]}}'행. –

+0

'@ a' 또는'@b'가 정의되어 있지 않음을 나타냅니다. –

+0

일치하지 않는 결과의 경우, 배열에있는'a_object' 또는'b_object'가 존재하지 않으면 0이되도록 할 수 있습니까? 예 : b_object가 존재하지 않기 때문에 [manufacturer_id, model_id, a_object, 0]' –

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 

, 당신은 merge 더 미묘한을 할 data.reduce에 전달 된 블록을 수정할 수 있습니다.

+0

당신이 제공 한 두 가지 접근 방식 모두에게 오류가 발생했습니다. '정의되지 않은 메소드'values_at 'for nil : NilClass''. 나는 API를 보았고 아무런 실마리가 없다. 왜 –

+0

두 배로 줄이는 것이 좋다. :). 여러분의 코드를 올바르게 이해한다면'@ a'와'@ b' 배열의 요소가'merge'에 응답 할 것으로 기대합니다. –

관련 문제