私はハッシュの配列を持っています、のようなもの
[ {:type=>"Meat", :name=>"one"},
{:type=>"Meat", :name=>"two"},
{:type=>"Fruit", :name=>"four"} ]
これに変換したい
{ "Meat" => ["one", "two"], "Fruit" => ["Four"]}
group_by
を試しましたが、これを取得しました
{ "Meat" => [{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}],
"Fruit" => [{:type=>"Fruit", :name=>"four"}] }
そして、完全なハッシュではなく名前だけを残すように変更することはできません。 Railsフォームのgrouped_options_for_select
のためであるため、これを1行で行う必要があります。
array.group_by{|h| h[:type]}.each{|_, v| v.replace(v.map{|h| h[:name]})}
# => {"Meat"=>["one", "two"], "Fruit"=>["four"]}
Steenslagの提案に従う:
array.group_by{|h| h[:type]}.each{|_, v| v.map!{|h| h[:name]}}
# => {"Meat"=>["one", "two"], "Fruit"=>["four"]}
初期配列に対する1回の反復で:
arry.inject(Hash.new([])) { |h, a| h[a[:type]] += [a[:name]]; h }
array = [{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"}]
array.inject({}) {|memo, value| (memo[value[:type]] ||= []) << value[:name]; memo}
私は以下のようにします:
hsh =[{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"}]
p Hash[hsh.group_by{|h| h[:type] }.map{|k,v| [k,v.map{|h|h[:name]}]}]
# >> {"Meat"=>["one", "two"], "Fruit"=>["four"]}
ActiveSuportの Hash#transform_values
:
array.group_by{ |h| h[:type] }.transform_values{ |hs| hs.map{ |h| h[:name] } }
#=> {"Meat"=>["one", "two"], "Fruit"=>["four"]}
@ ArupRakshit answer 、わずかに変更されました(最後の例ではわかりやすくするために関数が追加されています):
def group(list, by, at)
list.group_by { |h| h[by] }.map { |k,v| [ k , v.map {|h| h[at]} ] }.to_h
end
sample =[
{:type=>"Meat", :name=>"one", :size=>"big" },
{:type=>"Meat", :name=>"two", :size=>"small" },
{:type=>"Fruit", :name=>"four", :size=>"small" }
]
group(sample, :type, :name) # => {"Meat"=>["one", "two"], "Fruit"=>["four"]}
group(sample, :size, :name) # => {"big"=>["one"], "small"=>["two", "four"]}
質問には記載されていませんが、元のsample
をそのまま保持することをお勧めします。いくつかの回答はこれについて規定を維持しましたが、他の回答はそうではありませんでした。
グループ化(list.group_by {...}
)した後、(元のサンプルの値を変更せずに)変換を行う部分は次のとおりです。
.map { |k,v| [ k , v.map {|h| h[at]} ] }.to_h
いくつかのヒント:
Hash
のペア(最初のmap
)を反復します。ここで|group_key, array]
を受け取り、[group_key, new_array]
(外側のArray
)のblock
を返します。to_h
はArray of Array
sをHash
に変換します(この[[gk1,arr1],[gk2,arr2]...]
をこの{ gk1 => arr1, gk2 => arr2, ...}
に変換します)上記のステップ(2)で説明されていない1つの欠落したステップがあります。 new_array
はv.map {|h| h[at]}
によって作成され、at
の各元のHash
(h
)要素の値array
をキャストします(したがって、Array of Hash
esからArray
の要素に移動します)。
他の人が例を理解するのに役立つことを願っています。