2011-11-18 13 views
29

私はルビーで新しくなっていますので、noobishnessを許してください。ハッシュをCSVに保存するには

私は2列のCSVを持っています。 1つは動物の名前で、もう1つは動物のタイプです。 私はすべてのキーが動物の名前であり、値が動物のタイプであるハッシュを持っています。私はより高速なCSVを使用せずにハッシュをCSVに書きたいと思います。私はいくつかのアイデアを考えました。最も簡単なものは..基本的なレイアウトです。

require "csv" 

def write_file 
    h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' } 

    CSV.open("data.csv", "wb") do |csv| 
    csv << [???????????] 
    end 
end 

私はそれからの読み取りにファイルを開いたとき、私はそれFile.open("blabla.csv", headers: true) 戻っファイルに同じ方法を記述することも可能であろうが開かれましたか?

+0

私の質問に投票していただきありがとうございます。 :) – TheLegend

+3

Ruby 1.9は古いCSVモジュールをFasterCSVに置き換えたので、実際にはFasterCSVを使用しています。標準ライブラリの一部であるため、FasterCSVではなくCSVと呼ばれます。 –

答えて

39

これを試してみてください:

require 'csv' 
h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' } 
CSV.open("data.csv", "wb") {|csv| h.to_a.each {|elem| csv << elem} } 

が発生します:

1.9.2-p290:~$ cat data.csv 
dog,canine 
cat,feline 
donkey,asinine 
+0

ええ、それはアイデアでした。それを配列に戻してください..とてもクールな感謝!それを行うためにブロックを使用してプラス5ポイント!ハイタッチ! :)私はあなたがアップ時あなたの答えを悪い投票を – TheLegend

+3

。 :) – TheLegend

49

をあなたは、列のヘッダーをしたいとあなたが複数のハッシュを持っている場合:

require 'csv' 
hashes = [{'a' => 'aaaa', 'b' => 'bbbb'}] 
column_names = hashes.first.keys 
s=CSV.generate do |csv| 
    csv << column_names 
    hashes.each do |x| 
    csv << x.values 
    end 
end 
File.write('the_file.csv', s) 

は(Rubyの上でテスト1.9.3- p429)

+0

他に列ヘッダーも保存するために私のために働いた答えはありません。この答えはうまく動作します –

+0

'CSV.generate'は、実際にディスク上のファイルに出力したくない場合に非常に便利です。 – Beejamin

21

def write_file 
    hashes = [ { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' }, 
      { 'dog' => 'rover', 'cat' => 'kitty', 'donkey' => 'ass' } ] 

    CSV.open("data.csv", "w", headers: hashes.first.keys) do |csv| 
    hashes.each do |h| 
     csv << h.values 
    end 
    end 
end 
1

私はここで解決策を試してみましたが、間違った結果(間違った列の値)を得たので:すべて同じキーを共有する複数のハッシュで

def write_file 
    h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' } 

    CSV.open("data.csv", "w", headers: h.keys) do |csv| 
    csv << h.values 
    end 
end 

:あなたの元の質問への最も簡単な解決策私のソースは、常にキーのすべての値を持つとは限らないLDIFファイルです。私は以下を使用して終了しました。

最初に、ハッシュを構築するときに、別の配列のキーを覚えています。これは、既に存在しないキーで拡張します。

# building up the array of hashes 
File.read(ARGV[0]).each_line do |lijn| 
    case 
    when lijn[0..2] == "dn:" # new record 
     record = {} 
    when lijn.chomp == '' # end record 
     if record['telephonenumber'] # valid record ? 
      hashes << record 
      keys = keys.concat(record.keys).uniq 
     end 
    when ... 
    end 
end 

ここで重要な行は、新しいキー(ヘッダ)が発見されたキーの配列を延びるkeys = keys.concat(record.keys).uniqあります。

今最も重要:CSV

CSV.open("export.csv", "w", {headers: keys, col_sep: ";"}) do |row| 
    row << keys # add the headers 
    hashes.each do |hash| 
    row << hash # the whole hash, not just the array of values 
    end 
end 
1

に私たちのハッシュを変換するには、これを試してみてください:

require 'csv' 
data = { 'one' => '1', 'two' => '2', 'three' => '3' } 

CSV.open("data.csv", "a+") do |csv| 
     csv << data.keys 
     csv << data.values 
end 
3

CSVは、任意の順序でハッシュを取るの要素を除外し、していないparamsは省略することができますHEADERS

require "csv" 
HEADERS = [ 
    'dog', 
    'cat', 
    'donkey' 
] 

def write_file 

    CSV.open("data.csv", "wb", :headers => HEADERS, :write_headers => true) do |csv| 
    csv << { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' } 
    csv << { 'dog' => 'canine'} 
    csv << { 'cat' => 'feline', 'dog' => 'canine', 'donkey' => 'asinine' } 
    csv << { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine', 'header not provided in the options to #open' => 'not included in output' } 
    end 
end 

write_file # => 
# dog,cat,donkey 
# canine,feline,asinine 
# canine,, 
# canine,feline,asinine 
# canine,feline,asinine 

これは、CSVクラスでの作業をより柔軟で再なります敬虔な。 、d_odr:REV:

0

我々はハッシュを有するでき、

hash_1 = {1=>{:rev=>400, :d_odr=>3}, 2=>{:rev=>4003, :d_price=>300}} 

上記hash_1がそれらにいくつかのID 1,2-としてキー、..および値を有する再び(のようないくつかのキーでハッシュされます。 d_price)。 今、あなたは保存されてdesign_performance_data_temp.csvファイルを持っている、hash_1の値ごとに新しい配列を作成し、CSVファイルに挿入し、我々はCSVは、ヘッダーでファイルたい

CSV.open("design_performance_data_temp.csv", "w") do |csv| 
csv << headers 
csv_data = [] 
result.each do |design_data| 
    csv_data << design_data.first 
    csv_data << design_data.second[:rev] || 0 
    csv_data << design_data.second[:d_price] || 0 
    csv_data << design_data.second[:imp] || 0 
    csv_data << design_data.second[:d_odr] || 0 
    csv << csv_data 
    csv_data = [] 
end 
end 

headers = ['Designer_id','Revenue','Discount_price','Impression','Designer ODR'] 

を仮定あなたの対応するディレクトリにあります。 上記のコードをさらに最適化することができます。

関連する問題