5

I'm trying to convert this csv file:

cash,units,boxes,type
12,1,4,"beer"
12,5,4,"wine"
6,3,2,"sugar"
6,5,2,"oats"

to an array of just the rows and not the header. How does one do this?

I have this:

csv = CSV.read(input_path, headers: with_headers)

which gives me a csv object with 5 rows. How do I just convert the content to an array of 4 arrays, where each subarray represents a row?

1
  • I believe @steenslag's answer gives the correct result whereas the answer you selected does not (e.g., [12, 1, 4, "beer"], not ["12", "1", "4", "beer"]). No? Commented Jun 19, 2018 at 0:12

3 Answers 3

7

Simply convert the enumerator returned by CSV#each to an array, and shift it to get rid of the headers.

rows = CSV.open(input_path).each.to_a
rows.shift
rows
=> [["12", "1", "4", "beer"], ["12", "5", "4", "wine"], ["6", "3", "2", "sugar"], ["6", "5", "2", "oats"]]

If you prefer a more elegant solution and actually want to treat headers as such:

CSV.open(input_path, headers: true, return_headers: false).map(&:fields)

Please mind that in this case .each would yield CSV::Row objects, not arrays.

Sign up to request clarification or add additional context in comments.

6 Comments

I don't want the headers though.
Corrected, headers gone.
You need to update your return value as it still shows the headers as the first element of the array that is returned. I suggest drop(1) rather than shift as it avoid the need for the line rows.
@CarySwoveland thanks for pointing out the return value, corrected.
each.to_a.map is duplicitous where map would be sufficient. Right now it is Enumerator -> Array -> Array but since CSV includes Enumerable just map(&:fields) will return the Array
|
6
require "csv"

 p csv = CSV.table("test.csv").drop(1)

Output starts with [[12, 1, 4, "beer"],. that is: numbers where possible, not strings everywhere.

2 Comments

Readers: see the doc for CSV::table It's the same as CSV::new, except (as shown), three of the options keys are assigned default values, one being converters: :numeric, which converts "1" #=> 1, "1.4 #=> 1.4, "cat" => ."cat" and so on. The various options are documented for CSV::new.
Side note CSV includes Enumerable so CSV.table("test.csv").drop(1) is sufficient over to_a.drop(1) which causes Array -> Array
-2

I am not sure about this, but I would solve it in this way

CSV.read(path, {:row_sep => :auto, :col_sep => ','}).drop(1)

In your case I believe you have to indicate ',' in the attribute :col_sep

2 Comments

:col_sep defaults to "," which makes reasonable sense given "CSV" is traditionally an acronym for "Comma Separated Values"
If you're not sure about something its better suited as a comment than an answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.