Feature Request: Generate CSV String from Array
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
- It accepts the same options as
generateto customize its behavior - It's short and intuitive
Disadvantages
- A new method to remember
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.
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.
@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.
OK. Do you want to work on this? Or does @ericgpks want to work on this?
I would like to try this one !!
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.