anjali rai anjali rai - 4 years ago 182
Ruby Question

Process a file using hash

Below is the input file that I want to store into a hash table, sort it and output in the format shown below.

Input File

Name=Ashok, Email=ashok85@gmail.com, Country=India, Comments=9898984512
Email=raju@hotmail.com, Country=Sri Lanka, Name=Raju
Country=India, Comments=45535878, Email=vijay@gmail.com, Name=Vijay
Name=Ashok, Country=India, Email=ashok37@live.com, Comments=8898788987


Output File (Sorted by Name)

Name Email Country Comments
-------------------------------------------------------
Ashok ashok37@live.com India 8898788987
Ashok ashok85@gmail.com India 9898984512
Raju raju@hotmail.com Sri Lanka
Vijay vijay@gmail.com India 45535878





So far, I have read the data from the file and stored every line into an array, but I am stuck at hash[key]=>value

file_data = {}
File.open('input.txt', 'r') do |file|
file.each_line do |line|
line_data = line.split('=')
file_data[line_data[0]] = line_data[1]
end
end
puts file_data

Answer Source

Given that each line in your input file has pattern of key=value strings which are separated by commas, you need to split the line first around comma, and then around equals sign. Here is version of corrected code:

# Need to collect parsed data from each line into an array
array_of_file_data = []

File.open('input.txt', 'r') do |file| 

  file.each_line do |line| 

     #create a hash to collect data from each line
     file_data = {} 

     # First split by comma
     pairs = line.chomp.split(", ")

     pairs.each do |p|
        #Split by = to separate out key and value
        key_value = p.split('=') 
        file_data[key_value[0]] = key_value[1]  
     end

     array_of_file_data << file_data
   end 
end 
puts array_of_file_data

Above code will print:

{"Name"=>"Ashok", "Email"=>"ashok85@gmail.com", "Country"=>"India", "Comments"=>"9898984512"}
{"Email"=>"raju@hotmail.com", "Country"=>"Sri Lanka", "Name"=>"Raju"}
{"Country"=>"India", "Comments"=>"45535878", "Email"=>"vijay@gmail.com", "Name"=>"Vijay"}
{"Name"=>"Ashok", "Country"=>"India", "Email"=>"ashok37@live.com", "Comments"=>"8898788987"}

A more complete version of program is given below.

hash_array = []

# Parse the lines and store it in hash array
File.open("sample.txt", "r") do |f|
    f.each_line do |line|
       # Splits are done around , and = preceded or followed 
       # by any number of white spaces
       splits = line.chomp.split(/\s*,\s*/).map{|p| p.split(/\s*=\s*/)}

       # to_h can be used to convert an array with even number of elements
       # into a hash, by treating it as an array of key-value pairs
       hash_array << splits.to_h 
    end
end

# Sort the array of hashes
hash_array = hash_array.sort {|i, j| i["Name"] <=> j["Name"]}

# Print the output, more tricks needed to get it better formatted
header = ["Name", "Email", "Country", "Comments"]
puts header.join(" ")
hash_array.each do |h|
    puts h.values_at(*header).join(" ")
end

Above program outputs:

Name Email Country Comments
Ashok ashok85@gmail.com India 9898984512
Ashok ashok37@live.com India 8898788987
Raju raju@hotmail.com Sri Lanka 
Vijay vijay@gmail.com India 45535878

You may want to refer to Padding printed output of tabular data to have better formatted tabular output

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download