ruby / csv

CSV Reading and Writing
https://ruby.github.io/csv/
BSD 2-Clause "Simplified" License
182 stars 114 forks source link

Feature Request: Generate CSV String from Array #255

Closed okuramasafumi closed 2 years ago

okuramasafumi commented 2 years ago

Problem

When we have

array = [["foo", "bar"], [1, 2], [3, 4]]

one simple way to generate CSV String from this Array is:

header = array.shift
CSV::Table.new(array.map {|a| CSV::Row.new(header, a)}).to_csv # "foo,bar\n1,2\n3,4\n"

This works, but it's procedural and not intuitive.

It's often the case that it's easy to prepare data in form of Array, and difficult to prepare data in form of String, so it's good to have a way to directly convert Array into CSV String.

Solution

My suggestion is to add the method below:

CSV.generate_from_array(array) # "foo,bar\n1,2\n3,4\n"
CSV.generate_from_array(array, row_sep: "\r\n") # "foo,bar\r\n1,2\r\n3,4\r\n"

Advantages

Disadvantages

Implementtion

class CSV
  def self.generate_from_array(array, **options)
    CSV.generate(**options) do |csv|
      array.each do |row|
        csv << row
      end
    end
  end
end

This implementation works in my local environment. It's not optimized anyway.

kou commented 2 years ago

How about this?

diff --git a/lib/csv/core_ext/array.rb b/lib/csv/core_ext/array.rb
index 8beb06b..0180deb 100644
--- a/lib/csv/core_ext/array.rb
+++ b/lib/csv/core_ext/array.rb
@@ -4,6 +4,16 @@ class Array # :nodoc:
   #   ["CSV", "data"].to_csv
   #     #=> "CSV,data\n"
   def to_csv(**options)
-    CSV.generate_line(self, **options)
+    case first
+    when Array
+      output = +""
+      csv = CSV.new(output, **options)
+      each do |row|
+        csv << row
+      end
+      output
+    else
+      CSV.generate_line(self, **options)
+    end
   end
 end

If we use the suggested approach, I think that CSV.generate_lines(rows) is better.

okuramasafumi commented 2 years ago

@kou I like CSV.generate_lines(rows) API. I think we can have CSV.generate_lines(rows) and Array#to_csv for nested array at the same time.

kou commented 2 years ago

OK. Do you want to work on this? Or does @ericgpks want to work on this?

ericgpks commented 2 years ago

I would like to try this one !!

kou commented 2 years ago

OK! I'm waiting for your pull request for this! If you have any trouble, I can help you at https://gitter.im/red-data-tools/ja or pull request as usual.