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,, Country=India, Comments=9898984512, Country=Sri Lanka, Name=Raju
Country=India, Comments=45535878,, Name=Vijay
Name=Ashok, Country=India,, Comments=8898788987

Output File (Sorted by Name)

Name Email Country Comments
Ashok India 8898788987
Ashok India 9898984512
Raju Sri Lanka
Vijay 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 = {}'input.txt', 'r') do |file|
file.each_line do |line|
line_data = line.split('=')
file_data[line_data[0]] = line_data[1]
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 = []'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]  

     array_of_file_data << file_data
puts array_of_file_data

Above code will print:

{"Name"=>"Ashok", "Email"=>"", "Country"=>"India", "Comments"=>"9898984512"}
{"Email"=>"", "Country"=>"Sri Lanka", "Name"=>"Raju"}
{"Country"=>"India", "Comments"=>"45535878", "Email"=>"", "Name"=>"Vijay"}
{"Name"=>"Ashok", "Country"=>"India", "Email"=>"", "Comments"=>"8898788987"}

A more complete version of program is given below.

hash_array = []

# Parse the lines and store it in hash array"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 

# 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(" ")

Above program outputs:

Name Email Country Comments
Ashok India 9898984512
Ashok India 8898788987
Raju Sri Lanka 
Vijay 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