How to Export a Ruby Array into a single csv row? - ruby
I'm looking to pass an array into a csv as a single row. The code below showcases what I'm currently trying. The array is variable in length and will showcase something like this.
a = ["website url", "page link", "page link", "page link"]
The code essentially goes to a page using open-uri and scrapes out the links of each page. This is used for internal validation and checked against what we are expecting. If the link matches what we expect it is reported into the csv as a page link variable shown above.
I've currently tried using to_csv to format the data but inside the csv everything is in a single row including my comma separations.
def dwrite (array)
CSV.open("filename.csv", "ab") do |csv|
data = array.to_csv(row_sep: nil)
csv << [data]
end
end
This is an example of what the csv looks like in a single column:
https://www.url.com/example-page.html
#,
#,,
#,,,
#,,,,
#,,,,,
#,,,,,,
#,,,,,,,
#,,,,,,,,
#,,,,,,,,,
#,,,,,,,,,,
#,,,,,,,,,,,
#,,,,,,,,,,,,
#,,,,,,,,,,,,,
#,,,,,,,,,,,,,,
#,,,,,,,,,,,,,,,
https://anotherexamplepage.html
I was hoping that each array element passed into the method would showcase on the same line but this doesn't appear to be the case. Any help would be much appreciated.
You don't need to transform the array in any way. Just add it to the CSV:
def dwrite(array)
CSV.open("filename.csv", "ab") do |csv|
csv << array
end
end
Related
Parsing through excel using ruby gem "creek"
Hey guys so I am trying to parse through an excel file through the ruby gem "creek", it parses the the rows accurately but I want to just retrieve the Columns, such as only the data in the "A" cloumn. Outputs the whole excel documents correctly. require 'creek' creek = Creek::Book.new 'Final.xlsx' sheet= creek.sheets[0] sheet.rows.each do |row| puts row # => {"A1"=>"Content 1", "B1"=>nil, C1"=>nil, "D1"=>"Content 3"} end Any suggestions will be much appreciated.
Creek doesn't make it easy to extract column information because it stores the column and row smashed together in a string hash key. The more popular Roo allows you to do things like sheet.column(1) and get an entire column. Very simple. If you absolutely must have creek, I noticed that there is an add-on to Creek called Ditch which adds some column-fetching capability. Example: sheet.rows.each { |r| puts "#{r.index} #{r.get('A')} - #{r.get('B')}" } Finally, if you want to do it with Creek and no add-ons, use Hash#select: sheet.rows.each do |row| puts row.select{ |k,v| ["A", "B"].include? k[0]} end
To read the individual columns you can use Creek :: Sheet # simple_rows method For example, to read the first and third columns: require 'creek' creek = Creek::Book.new 'Final.xlsx' sheet_first = creek.sheets.first # read first column A col_first = sheet_first.simple_rows.map{|col| col['A']} #=> Array containing the first column # read third column C col_third = sheet_first.simple_rows.map{|col| col['C']} #=> Array containing the third column
Ruby equivalent to Python's DictWriter?
I have a Ruby script that goes through a CSV, determines some information, and then puts out a resulting CSV file. In Python, I'm able to open both my source file and my results file with DictReader and DictWriter respectively and write rows as dictionaries, where keys are the file header values. It doesn't appear that there is a manageable way to do this in Ruby, but I'm hoping somebody can point me to a better solution than storing all of my result hashes in an array and writing them after the fact.
The standard library "CSV" gives rows hash-like behavior when headers are enabled. require 'csv' CSV.open("file.csv", "wb") do |csv_out| CSV.foreach("test.csv", headers: true) do |row| row["header2"].upcase! # hashlike behaviour row["new_header"] = 12 # add a new column csv_out << row end end (test.csv has a header1, a header2 and some random comma separated string lines.)
Ruby - Matching a value and returning a corresponding value from a separate file
I'm looking to match one value (A sku from a website) to the same value (A sku from lookup.csv) and return a corresponding model (From lookup.csv). Here's sample data from lookup.csv: SKU , Model 2520045 , DQ.SUNAA.002 7423599 , DA.MX00.1CC 9547543 , DX.MF01.2BM Here's my code thus far: url = "http://www.bestbuy.com/site/acer-aspire-23-touch-screen-all-in-one-intel-core-i5-8gb-memory-2tb-hard-drive-black/2520045.p?id=1219547718151&skuId=2520045" page = Nokogiri::HTML(open(url)) sku = page.css('span#sku-value').text #model = match the sku to the sku in lookup.csv and return corresponding model puts model I know that I can open the file with open("lookup.csv", 'r') but past that, I'm not quite sure how to match/return a corresponding value. Any help is appreciated!
The suggestion of Aoukar would work but be slow with large data sets. Here a better solution, read the CSV once, using the CSV gem (no need to reinvent the wheel) and store the data in a hash, after that you can just ask fort the right Model, here a working sample. I'm using the CSV data in the DATA part of the script here so I don't need the CSV file itself. require "csv" lookup = {} CSV.parse(DATA, col_sep: " , ", headers: true, force_quotes: false, :quote_char => "\x00").each do |row| lookup.merge! Hash[row['SKU'], row['Model']] end lookup #{"2520045"=>"DQ.SUNAA.002", "7423599"=>"DA.MX00.1CC", "9547543"=>"DX.MF01.2BM"} lookup['2520045'] #"DQ.SUNAA.002" __END__ _ ,SKU , Model #the first element is to work around a bug in CSV used this way 2520045 , DQ.SUNAA.002 7423599 , DA.MX00.1CC 9547543 , DX.MF01.2BM
you can try this code, but I didn't test it so it might need some modifications, I've written it as a function since it's what I'm used to. def search(path,key) #path to file, and word to search for File.open(path,'r') do |file| #open file file.readlines.each { |line| #read lines array if line.split(' , ')[0] == key #match the SKU return line.split(' , ')[1] #return the Model end } end end
Using excel to log results in ruby watir. how to keep values in different cells using puts
I am new to ruby watir and need your help. I am using the following commands to log my script results into an excel sheet. File.open('c:\log.txt', 'w') do |file| file.puts("TEST PASSED" + "#{Time.now}") end Here the test passed and the time is getting displayed in a single cell itself. I want to display both of it in different cells. Please suggest a solution. Thanks in advance!
you are logging to a file called log.txt which appears to be a plain text file. if you want your file to be an excel file you will need a format, the easiest one to write to is either .csv or .tsv which stands for comma separated variable and tab separated variables. You could then write in a few different ways. You could write as you were with: File.open('c:\log.tsv', 'w') do |file| file.puts("TEST PASSED\t" + "#{Time.now}") end for a tsv (note that it doesn't need to be called .tsv) File.open('c:\log.csv', 'w') do |file| file.puts("TEST PASSED," + "#{Time.now}") end for a csv or you could use the standard csv library. like so: CSV.open("c:\log.csv", "wb") do |csv| csv << ["TEST PASSED", "#{Time.now}"] end which you can manipulate for tsv's: CSV.open("c:\log.csv", "wb", { :col_sep => "\t" }) do |csv| csv << ["TEST PASSED", "#{Time.now}"] end
The easiest solution would probably be to log the results in a CSV (comma separated values) file. These can be written like a text file, as well as read by Excel as a grid. For a CSV file, each line represents a row in the table. Within each line, the column values (or cells) are separated by commas. For example, the following will create 2 rows with 3 columns: a1, b1, c1 a2, b2, c2 For your logging, you could: Create a log.csv instead of log.txt Output the values as comma separated The code would be: File.open('c:\log.csv', 'w') do |file| file.puts("TEST PASSED, #{Time.now}") end
How not to save to csv when array is empty
I'm parsing through a website and i'm looking for potentially many million rows of content. However, csv/excel/ods doesn't allow for more than a million rows. That is why I'm trying to use a provisionary to exclude saving empty content. However, it's not working: My code keeps creating empty rows in csv. This is the code I have: # create csv CSV.open("neverending.csv", "w") do |csv| csv << ["kuk","date","name"] # loop through all urls File.foreach("neverendingurls.txt") do |line| begin doorzoekbarefile = Nokogiri::HTML(open(line)) for k in 1..999 do # PROVISIONARY / CONDITIONAL unless doorzoekbarefile.at_xpath("//td[contains(style, '60px')])[#{k}]").nil? # xpaths kuk = doorzoekbarefile.at_xpath("(//td[contains(#style,'60px')])[#{k}]") date = doorzoekbarefile.at_xpath("(//td[contains(#style, '60px')])[#{k}]/following-sibling::*[1]") name = doorzoekbarefile.at_xpath("(//td[contains(#style, '60px')])[#{k}]/following-sibling::*[2]") # save to csv csv << [kuk,date,name] end end end rescue puts "error bij url #{line}" end end end Anybody have a clue what's going wrong or how to solve the problem? Basically I simply need to change the code so that it doesn't create a new row of csv data when the xpaths are empty.
This really doesn't have to do with xpath. It's simple Array#empty? row = [kuk,date,name] csv << row if row.compact.empty? BTW, your code is a mess. Learn how to indent at least beore posting again.