2016-06-28 11 views
1

私はネストされた配列/ハッシュにルビーuniqの使い方

# Json array 
a ={ 
    results: [ 
    { 
    employee: { 
     name: "A", 
     employee_id: "A-00016", 
     title: 1 
    } 
    },{ 
    employee: { 
     name: "A", 
     employee_id: "A-00016", 
     title: 2 
    } 
    },{ 
    employee: { 
     name: "C", 
     employee_id: "C-00017", 
     title: 3 
    } 
    } 
    ] 
    } 



# Calling uniq on a 
a.uniq { |p| p.values_at(:employee_id) } 

しかし、それは唯一のEMPLOYEE_IDにユニークな結果ベースを返すように、フォローJSONでuniqのメソッドを呼び出すためにしようとしています、私はこれだけを取得しています結果

{ 
    results: [ 
    { 
    employee: { 
     name: "A", 
     employee_id: "A-00016", 
     title: 1 
    } 
    } 
    ] 
    } 

代わりに私が何をしたいの

{ 
    results: [ 
    { 
    employee: { 
     name: "A", 
     employee_id: "A-00016", 
     title: 1 
    },{ 
    employee: { 
     name: "C", 
     employee_id: "C-00017", 
     title: 3 
    } 
    } 
    ] 
    } 

私は、正しい方法を使用しています出力します私は欲しいのですか? uniq

+0

私は、 'a [:results] .uniq!'を実行することをお勧めしますが、最初のインスタンスではtitle = 1、2番目のインスタンスではtitle = 2です。したがって、ルビーは最初の2つを異なるものと見なします。 – oliviergg

答えて

1

はここで、我々が使用することができます変更された入力hashを返すために、これを行うための一つの方法である場所に配列a[:results]を変更しますuniq!dupを使用して、保護するためにハッシュaを複製し、次にtapを使用して複製されたハッシュを操作します。

r = a.dup.tap do |h| 
    h[:results].uniq! do |h| 
    h[:employee][:employee_id] 
    end 
end 

#=> {:results=> 
# [ 
#  {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>1}}, 
#  {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}} 
# ] 
# } 
+0

ありがとうございます!方法は動作しますが、uniqを使用しているので、私は@ mudasobwaの答えに投票しました。 –

+0

@TomCheung他の答えは、望ましい出力を生成しません。この解決法は 'uniq! 'を使って所望の出力を得る。 –

+0

Tom、Wandがポイントを持つ。 –

3

input[:results].uniq { |e| e[:employee][:employee_id] } 
#⇒ [ 
# {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>"1"}}, 
# {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>"3"}}] 

しかし、私は同じidを持つ兄弟姉妹から選択するものに適用されるいくつかの条件があるはずと信じています。以下のコードは、最大titleの値を有する、いずれかを選択:

input[:results].group_by { |e| e[:employee][:employee_id] } 
       .map { |_, v| v.max_by { |e| e[:employee][:title].to_i } } 
#⇒ [ 
# {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>"2"}}, 
# {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>"3"}}] 
1
def selection_criterion(h) 
    h[:title].to_i 
end 

{results: a[:results].group_by {|h| h[:employee][:employee_id]}. 
         values. 
         map {|arr| arr.max_by {|h| selection_criterion(h[:employee])}}} 
    #=> {:results=> 
    #  [{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}}, 
    #  {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}]}   

所望通りselection_criterionを定義し、min_byに可能変更max_by

手順は次のとおりです。

b = a[:results] 
    # => [{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>1}}, 
    #  {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}}, 
    #  {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}] 
c = b.group_by { |h| h[:employee][:employee_id] } 
    #=> {"A-00016"=>[{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>1}}, 
    #    {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}}], 
    # "C-00017"=>[{:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}]} 
d = c.values 
    #=> [[{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>1}}, 
    #  {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}}], 
    # [{:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}]] 
e = d.map { |arr| arr.max_by { |h| selection_criterion(h[:employee]) } } 
    #=> [{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}}, 
    # {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}] 
{ results: e } 
    #=> {:results=> 
    #  [{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}}, 
    #  {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}]}   
関連する問題