Importing CSV Data into a Ruby Array/Variable

Importing CSV data into a ruby array/variable

If you try to use FasterCSV in Ruby 1.9 you get a warning saying that the standard Ruby 1.9 CSV library is actually faster. So I used the standard Ruby CSV library. This should work in Ruby 1.9 or 1.8.7.

require 'csv'

module MyConfig
@mac_address_hash = {}
CSV.foreach("config.csv") do |row|
name, mac_address = row
next if name == "Name"
@mac_address_hash[name] = mac_address
end

puts "Now we have this hash: " + @mac_address_hash.inspect

def self.mac_address(computer_name)
@mac_address_hash[computer_name]
end

end

puts "MAC address of Desktop: " + MyConfig.mac_address("Desktop")

The output of this code is:

Now we have this hash: {"Computer"=>" 02-46-81-02-46-cd", "Desktop"=>" 01-23-45-67-89-ab"}
MAC address of Desktop: 01-23-45-67-89-ab

Now what I want you to do is read every line of this code carefully and try to understand what it does and why it is necessary. This will make you a better programmer in the long run.

You could improve this code to lazily load the CSV file the first time it is required.

import from CSV into Ruby array, with 1st field as hash key, then lookup a field's value given header row

To get the best of both worlds (very fast reading from a huge file AND the benefits of a native Ruby CSV object) my code had since evolved into this method:

$stock="XTEX"
csv_data = CSV.parse IO.read(%`|sed -n "1p; /^#{$stock},/p" stocks.csv`), {:headers => true, :return_headers => false, :header_converters => :symbol, :converters => :all}

# Now the 1-row CSV object is ready for use, eg:
$company = csv_data[:company][0]
$volatility_month = csv_data[:volatility_month][0].to_f
$sector = csv_data[:sector][0]
$industry = csv_data[:industry][0]
$rsi14d = csv_data[:relative_strength_index_14][0].to_f

which is closer to my original method, but only reads in one record plus line 1 of the input csv file containing the headers. The inline sed instructions take care of that--and the whole thing is noticably instant. This this is better than last because now I can access all the fields from Ruby, and associatively, not caring about column numbers anymore as was the case with awk.

How to store a specific element from a csv into a variable?

To read this in quickly if it's a small file and memory isn't a constraint:

CSV.open('CSV/energy.csv').read[1][1]

Where that pulls the second row's second value as everything's zero-indexed in Ruby.

In your code you have it wrapped inside of a class definition but that doesn't really make sense unless you're defining methods. Yes you can run executable code there in that context but that's reserved for other situations like meta-progamming.

A Ruby-style design looks like this:

class CSVReader
def initialize(path)
@path = path
end

def value(row: 1, col: 1)
CSV.open(@path).read[row][col]
end
end

Where you can call it like:

CSVReader.new('CSV/energy.csv').value
CSVReader.new('CSV/energy.csv').value(row: 4, col: 2)

And so on.

Creating a ruby file from CSV data?

My reputation is not high enough to ask you more questions about your requirements via comments, but here are a few facts that might help.

I am assuming that you have populated a Rails model with the information you need. I have no sample code from you so I'll provide an example with a 'Book' model. The Book model has a title and an author, both of type String.

target = "file.txt"
contents = ""

# Get all books as an array. Arrays have iterators so we can use 'each'
Book.all.each do |book|
# get the book title, append it to the string. Add a newline
contents.concat(book.title).concat($/)

# get the book author
contents.concat(book.author).concat($/)

# Just a line separator
contents.concat("-----").concat($/)
end
File.open(target, "w").write(contents)

The above would yield something like this inside the text file:

Book 1
Author 1
-----
Book 2
Author 1
-----
...

Reading up more on the Rails active records might help you as well: ActiveRecord

Ruby on Rails - Import Data from a CSV file

require 'csv'    

csv_text = File.read('...')
csv = CSV.parse(csv_text, :headers => true)
csv.each do |row|
Moulding.create!(row.to_hash)
end

Output array to CSV in Ruby

To a file:

require 'csv'
CSV.open("myfile.csv", "w") do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end

To a string:

require 'csv'
csv_string = CSV.generate do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end

Here's the current documentation on CSV: http://ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html

ruby - create CSV::Table from 2d array

You can create a CSV::Table object with headers from a 2D array using CSV.parse.

First convert your 2d array to a string where the values in each row are joined by a comma, and each row is joined by a newline, then pass that string to CSV.parse along with the headers: true option

require 'csv'

sample_array = [
["column1", "column2", "column3"],
["r1c1", "r1c2", "r1c3"],
["r2c1", "r2c2", "r2c3"],
["r3c1", "r3c2", "r3c3"],
]

csv_data = sample_array.map {_1.join(",")}.join("\n")
table = CSV.parse(csv_data, headers: true)

p table
p table.headers
p table[0]
p table[1]
p table[2]

=>

#<CSV::Table mode:col_or_row row_count:4>
["column1", "column2", "column3"]
#<CSV::Row "column1":"r1c1" "column2":"r1c2" "column3":"r1c3">
#<CSV::Row "column1":"r2c1" "column2":"r2c2" "column3":"r2c3">
#<CSV::Row "column1":"r3c1" "column2":"r3c2" "column3":"r3c3">


Related Topics



Leave a reply



Submit