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
Rails on Netbeans: Uncaught Exception: No Such File to Load - Script/Server or Script/Console
Binding to Networking Interfaces in Ruby
Typeerror: Can't Convert Net::Httpok into String
Posting Ruby Data in JSON Format with Net/Http
Download a Carrierwave Upload from S3
Robust Way to Deploy a Rack Application (Sinatra)
Best/Most Elegant Way to Share Objects Between a Stack of Rack Mounted Apps/Middlewares
Camelcase Instead of Snake_Case in Rails Db
Rails Routes: Nested, Member, Collection, Namespace, Scope and Customizable
Require Tree in Asset Pipeline
Unit Testing Code Which Gets Current Time
Using Rails Form Helpers with Serialized Custom Classes
Can't Log into Active Admin. Any Way to Create an Admin User
Rails Asset Pipeline and Digest Values
How to Tell a Ruby Method to Expect a Specific Parameter Type