I am trying to write a ruby script that will take all of the CSVs in a given directory and map their headers out so that duplicate columns will match up and columns unique to a file will have their own column in the final data file. The following code produces the output I desire, however something about it seems overly complicated and clumsy. Are there better practices or patterns I should follow to accomplish this? For example it seems to me like the master_hash variable should lose scope when I transfer it to the key_arr, but when I try to make the code reflect that I end up overwriting it each time I open a new file. Am I trying to hard to avoid "slurping" the files? Can this be done using less memory/faster? Forgive me if this question is too general in nature and if I can improve it to be more useful please let me know.
require 'CSV'
key_arr = [] # create Key array to store the headers
master_hash = {} # create master hash to consolidate headers
# get each csv in file
Dir.glob('datasample*.csv').each do |file|
# open each csv
File.open(file) do |csv|
# Create a temporary hash of the headers
temp_hash = Hash[csv.readline.split(',').map.with_index.to_a]
# merge temporary hash to master hash
master_hash = master_hash.merge(temp_hash)
end
key_arr = master_hash.keys # Put keys from hash into array
end
CSV.open('dest.csv', 'w') do |dest_csv| # open destination file
dest_csv << key_arr # write header row
end
Dir.glob('datasample*.csv').each do |file| # get all the csv's to be merged
# Open destination file in append mode
CSV.open('dest.csv', 'a', headers: true) do |dest_csv|
# open each source file for reading
CSV.open(file, headers: true) do |source_csv|
source_csv.each do |row| # iterate over each row of the source file
row_arr = Array.new(key_arr.length) # create array to hold Row
row.each do |cell| # get each header/field combination
# iterate over the key arr
# (key arr is the total number of fields on the final csv)
key_arr.length.times do |master_key_index|
# check if the header for the selected cell matches the header
# at the index on the key array to determine position in row array
if cell[0] == key_arr[master_key_index]
# set row array element to cell value if a match
row_arr[master_key_index] = cell [1]
end
end
end
dest_csv << row_arr # Write row to dest_csv
end
end
end
end
While the scale of this individual script is relatively small and performance isn't a huge concern per se, I would rather get into the habit of using the "right" tools for the job than just guessing. Also, sorry about any formatting issues here. I can put this on gist if need be.