2011-11-18 32 views
29

Tôi mới trong ruby ​​vì vậy xin vui lòng tha thứ cho sự noobishness.Làm thế nào để lưu một băm vào một CSV

Tôi có CSV với hai cột. Một cho tên động vật và một cho loại động vật. Tôi có một băm với tất cả các phím là tên động vật và các giá trị là loại động vật. Tôi muốn viết băm vào CSV mà không cần sử dụngCSV nhanh hơn. Tôi đã nghĩ về một số ý tưởng những gì sẽ là dễ nhất .. đây là cách bố trí cơ bản.

require "csv" 

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

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

Khi tôi mở tập tin để đọc từ nó tôi mở nó File.open("blabla.csv", headers: true) Nó sẽ có thể phải viết lại các tập tin cùng một cách?

+0

cảm ơn bạn đã bỏ phiếu cho câu hỏi của tôi. :) – TheLegend

+3

Để bạn biết, Ruby 1.9 đã thay thế mô-đun CSV cũ bằng FasterCSV, vì vậy bạn đang thực sự sử dụng FasterCSV. Vì nó là một phần của Thư viện chuẩn nên nó được gọi là CSV thay vì FasterCSV. –

Trả lời

39

Hãy thử điều này:

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

Sẽ cho kết quả:

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

yeah đó là ý tưởng. chuyển đổi nó trở lại một mảng .. cảm ơn rất mát mẻ! và sử dụng một khối để làm điều đó cộng với 5 điểm !! đập tay! :) – TheLegend

+3

bỏ phiếu bầu lên câu trả lời của bạn khi tôi lvl lên. :) – TheLegend

49

Nếu bạn muốn tiêu đề cột và bạn có nhiều băm:

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) 

(thử nghiệm trên Ruby 1.9.3- p429)

+0

Không có câu trả lời nào khác phù hợp với tôi để lưu các tiêu đề cột. Câu trả lời này chỉ hoạt động tốt –

+0

'CSV.generate' rất tiện dụng nếu bạn không muốn thực sự xuất ra một tệp trên đĩa. – Beejamin

21

Tôi nghĩ rằng Giải pháp đơn giản nhất cho câu hỏi ban đầu của bạn:

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 

Với nhiều băm rằng tất cả các chia sẻ các phím cùng:

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

Tôi đã thử các giải pháp ở đây nhưng có một kết quả không chính xác (giá trị trong cột sai) kể từ nguồn của tôi là một tệp LDIF không phải lúc nào cũng có tất cả các giá trị cho một khóa. Tôi đã kết thúc bằng cách sử dụng sau đây.

Trước tiên, khi xây dựng băm tôi nhớ các phím trong một mảng riêng biệt mà tôi mở rộng với các phím mà không phải là allready ở đó.

# 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 

Dòng quan trọng ở đây là keys = keys.concat(record.keys).uniq mở rộng mảng khóa khi tìm thấy khóa mới (tiêu đề).

Bây giờ quan trọng nhất: chuyển đổi băm của chúng tôi để một 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

Hãy thử điều này:

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 có thể mất một băm trong bất kỳ thứ tự, loại trừ yếu tố, và bỏ qua một không params trong số 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 

Điều này giúp làm việc với lớp CSV linh hoạt hơn và tái có thể sử dụng được.

0

Cho phép chúng tôi có một băm,

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

Các hash_1 trên có các phím như một số id 1,2, .. và các giá trị cho những người đang một lần nữa băm với một số phím như (: rev,: d_odr,: d_price). Giả sử chúng ta muốn nộp với tiêu đề CSV,

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

Sau đó tạo một mảng mới cho mỗi giá trị của hash_1 và chèn nó trong tập tin 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 

Bây giờ bạn đang gặp design_performance_data_temp.csv tập tin đã lưu trong thư mục tương ứng của bạn. Mã trên có thể được tối ưu hóa thêm.

Các vấn đề liên quan