inquisitive
inquisitive

Reputation: 3974

convert a string to hash of array in the specified format ruby

I have data of the form:

Manju She is a good girl
Raja He is okay boy
Manju She comes late in the class
Raja He is punctual

I want to create such a structure from this:

manju_hash = {"Manju1" => ["She", "is", "a","good","girl"], "Manju2" => ["She", "comes","late", "in", "the","class"]}
raja_hash = {"Raja1" => ["He", "is", "okay", "boy"],  "Raja2" => ["He", "is", "punctual"]}

This is the code that I've written:

manju_hash = Hash.new
raja_hash = Hash.new
 data_lines.split(/\n+/).each do |val|
    value =val.split(/\s+/)
    key = value[0]
    if (key=='Manju')
      value.delete(key)    
      manju_hash.merge!(key+(manju_hash.size+1).to_s => value)
    elsif (key=='Raja')
      value.delete(key)    
      raja_hash.merge!(key+(raja_hash.size+1).to_s => value)
   end
 end

Is this the right way to achieve this, or there is some other idiomatic ruby way? Some other improvement that I could do

Upvotes: 0

Views: 74

Answers (2)

pangpang
pangpang

Reputation: 8821

I just made some refactoring, the algorithm is same as you.......

data = "Manju She is a good girl\nRaja He is okay boy\nManju She comes late in the class\nRaja He is punctual"

hash = data.split("\n").map {|e| e.split(" ")}.group_by {|e| e[0] }
#{"Manju"=>[["Manju", "She", "is", "a", "good", "girl"], ["Manju", "She", "comes", "late", "in", "the", "class"]], "Raja"=>[["Raja", "He", "is", "okay", "boy"], ["Raja", "He", "is", "punctual"]]}  

def function(data)
    hash = Hash.new
    data.each_with_index {|e, i| hash.merge!((e[0]+(i+1).to_s) => e[1..-1])}
    hash
end



function(hash["Manju"])
    => {"Manju1"=>["She", "is", "a", "good", "girl"], "Manju2"=>["She", "comes", "late", "in", "the", "class"]}

function(hash["Raja"])
=> {"Raja1"=>["He", "is", "okay", "boy"], "Raja2"=>["He", "is", "punctual"]}

Upvotes: 1

Rob Falken
Rob Falken

Reputation: 2297

This is a bit less repetitive, and without the if/else-thingie

hash = {}
counter = {}
data_lines.split(/\n+/).each do |line|
  key, value = line.split(' ', 2)
  counter[key] = counter[key].to_i + 1
  hash[key] = {} unless hash.has_key?(key)
  hash[key][key + counter[key].to_s] = value.split(' ')
end

manju_hash = hash['Manju']
raja_hash = hash['Raja']

A walkthrough to make it more clear (because I didn't want to add comments in the code), basically what it does is:

  • split the text chunk into lines
  • split each line on space, but limiting it to separate key from value
  • keep count of how many times a key has been used to append it properly
  • add the top-level key if it's the first time, Raja for instance, occurs
  • add your array of words to a key appended with the counter number

Upvotes: 1

Related Questions