web-dev-qa-db-ja.com

ハッシュをCSVに保存する方法

私はRubyの初心者です。

2列のCSVがあります。 1つは動物名用、もう1つは動物タイプ用です。すべてのキーが動物名で、値が動物タイプであるハッシュがあります。 fastCSVを使用せずに、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)を開きました。同じ方法でファイルに書き戻すことはできますか?

36
TheLegend

これを試して:

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
40
Sławosz

列ヘッダーが必要で、複数のハッシュがある場合:

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でテスト済み))

54
Joe Goggins

私はあなたの元の質問に対する最も簡単な解決策だと思います:

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

複数のハッシュすべてが同じキーを共有する

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
24
Tom Rossi

CSVは任意の順序でハッシュを取得し、要素を除外し、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クラスの操作がより柔軟で読みやすくなります。

10
rudolph9

ここで解決策を試してみましたが、ソースがキーのすべての値を常に持っているとは限らない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
_
4
peter

これを試して:

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

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

ハッシュを作ってみましょう。

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

上記のhash_1は、いくつかのid 1,2、..としてキーを持ち、それらの値は(:rev、:d_odr、:d_price)としていくつかのキーを持つハッシュです。ヘッダー付きのCSVファイルが必要だとします。

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

次に、hash_1の各値に対して新しい配列を作成し、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

これで、対応するディレクトリにdesign_performance_data_temp.csvファイルが保存されました。上記のコードはさらに最適化できます。

0
shubham mishra