7

ハッシュを CSV 行にマップしたいと思います。

ハッシュにいくつかのオブジェクトがあります。

person1 = {'first_name' => 'John', 'second_name' => 'Doe', 'favorite_color' => 'blue', 'favorite_band' => 'Backstreet Boys'}
person2 = {'first_name' => 'Susan', 'favorite_color' => 'green', 'second_name' => 'Smith'}

これを、キーを列として、各行の値を含む CSV ファイルに変換したいと考えています。

次のように作成することで、ヘッダーを簡単に作成できますCSV::Row

h = CSV::Row.new(all_keys_as_array,[],true)

私は順序に頼ることができず、さらに重要なことに、すべての値が常に満たされるわけではありません。

しかし<<、配列を介してテーブルに行を追加しようとすると、ヘッダーのマッピングは無視されます。正しい順序である必要があります。

これを実証するために、次の小さなスクリプトを書きました。

require 'csv'

person1 = {'first_name' => 'John', 'second_name' => 'Doe', 'favorite_color' => 'blue', 'favorite_band' => 'Backstreet Boys'}
person2 = {'first_name' => 'Susan', 'favorite_color' => 'green', 'second_name' => 'Smith'}

persons = [person1, person2]
all_keys_as_array = %w{first_name second_name favorite_color favorite_band}

h = CSV::Row.new(all_keys_as_array,[],true)
t = CSV::Table.new([h])

persons.each do |p|
  r = CSV::Row.new([],[],false)
  p.each do |k, v|
    r << {k => v}
  end
  t << r
end

puts t.to_csv

私はこの出力を期待します:

first_name,last_name,favorite_color,favorite_band
John,Doe,blue,Backstreet Boys
Susan,Smith,green,

代わりに、表示される順序で値が表示されます。したがって、出力は次のようになります。

first_name,second_name,favorite_color,favorite_band
John,Doe,blue,Backstreet Boys
Susan,green,Smith

最も奇妙な部分は、['key']正しい値を取得することでルックアップを行うことです:

puts "favorite_bands: #{t['favorite_band']}"
> favorite_bands: [nil, "Backstreet Boys", nil]

期待どおりにCSVファイルに書き込む方法はありますか?

4

3 に答える 3

5

現在の提案はどちらも機能するため、これに感謝します。

ただし、 CSV::Row#fieldsを使用して、より洗練されたソリューションを見つけました。

次に、テーブルに追加する前に、CSV 行を正しい配列に変換するだけです。

t << r.fields(*all_keys_as_array)
于 2013-03-02T16:13:08.123 に答える
5

列名を反復するだけです

persons.each do |person|
  r = CSV::Row.new([],[],false)
  all_keys_as_array.each do |key|
    r << person[key]
  end
  t << r
end
于 2013-03-01T16:37:10.647 に答える
3

#to_csvすべてのものを使用して省くCSV::RowことCSV::Tableができる場合があります。

headers = %w{first_name second_name favorite_color favorite_band} # fyi if you have commas in here you'll get messed up

people = []
people << {'first_name' => 'John', 'second_name' => 'Doe', 'favorite_color' => 'blue', 'favorite_band' => 'Backstreet Boys'}
people << {'first_name' => 'Susan', 'favorite_color' => 'green', 'second_name' => 'Smith'}

require 'csv'
File.open('output.csv', 'w') do |f|
  f.puts headers.to_csv
  people.each do |person|
    f.puts headers.map { |h| person[h] }.to_csv
  end
end
于 2013-03-01T17:58:44.540 に答える