5

次の配列があります。

myarray = [
  ['usa','primary', 'john'],
  ['france','primary', 'lira'],
  ['usa', 'secondary', 'steve'],
  ['germany', 'primary', 'jeff'],
  ['france', 'secondary', 'ben']
]

次のようなハッシュの配列に変換したい:

[
  {:country => 'usa', :primary => 'john', :secondary => 'steve'},
  {:country => 'france', :primary => 'lira', :secondary => 'ben'},
  {:country => 'germany', :primary => 'jeff', :secondary => ''}
]

配列をループし、値を「プライマリ」のハッシュに入れることでそれを行うことができます。配列に既に挿入されている可能性のある既存のハッシュに「セカンダリ」を追加するにはどうすればよいですか?

4

2 に答える 2

11

少し高次のプログラミングを使用すると、次のようになります。

myarray.reduce({}) do |accu, (country, func, name)| 
  accu[country] ||= {}
  accu[country][func.to_sym] = name
  accu 
end.map{|k, h| h[:country] = k; h}

説明:

Reduce はアキュムレータを使用します。この場合、空のハッシュから開始して配列を調べます。配列内のトリプルを変数に一致させますcountry, func, name。国ごとにグループ化したいので、それを最初のハッシュキーとして作成します。ハッシュが含まれている必要があるため、 が の配列に対応していることを確認しaccu[country] ||= {}ます。

func次に、シンボルに変換するキーと値のペアを追加します。最後に、次の反復に渡される変更されたアキュムレータを返します。

これにより、次のようなデータ構造が返されます。

{"usa"=>{:primary=>"john", :secondary=>"steve"}, 
 "france"=>{:primary=>"lira", :secondary=>"ben"}, 
 "germany"=>{:primary=>"jeff"}} 

次に、大きなハッシュではなく、ハッシュの配列に変換する必要があります。これを呼び出すことでこれを行い、その過程でハッシュにキーとしてmap追加します。country

上記のアルゴリズムが行わないことの 1 つは、欠損値のチェックです。:primaryとの両方が存在することを保証するものではありません:secondary。を次のように変更することで、mapこれを行うことができます。

.map do |k, h|
  h[:country] = k
  h[:primary] ||= ""
  h[:secondary] ||= ""
  h
end
于 2012-10-18T23:29:38.220 に答える
5

Here's a fun, albeit confusing, way to do it.

format = Hash.new{ |h,k| h[k] = {:country => k, :primary => '', :secondary => ''} }

myarray.inject(format){ |result, (c,k,v)| result[c][k.to_sym] = v; result }.values

# => [
  {:country=>"usa", :primary=>"john", :secondary=>"steve"},
  {:country=>"france", :primary=>"lira", :secondary=>"ben"},
  {:country=>"germany", :primary=>"jeff", :secondary=>""} ]

基本的に、formatハッシュは出力を生成する方法を定義します。このinject呼び出しにより、国別に結果が収集されます。このvalues呼び出しは、国のハッシュ キーなしで実際の結果を取得するだけです。

于 2012-10-19T00:22:24.017 に答える