Reputation: 155
Im wondering if there is a better way of converting a string to a Hash. My String will always look exactly the same regarding the structure. Here is an example:
string = "range:12\ntype:default\n"
@settings = Hash[
*string.downcase
.split("\n")
.map{|s| [s.split(":")[0].to_sym, s.split(":")[1]]}
.flatten
]
p @settings
# => {:range=>"12", :type=>"default"}
This does what it should do and I have no problems with this. But it is extremely unreadable and I hope that there are some refactoring options for my code.
Upvotes: 2
Views: 3351
Reputation: 29124
Hash[*string.split(/[:\n]/)]
# => {"range"=>"12", "type"=>"default"}
Upvotes: 6
Reputation: 54684
You can use String.scan
to search for key-value pairs in the string and then convert the resulting array of arrays to a hash by simply calling to_h
:
string.scan(/(.+):(.+)\n/).to_h
#=> {"range"=>"12", "type"=>"default"}
If you really need the symbol keys, you can use Array#map
before converting to a hash:
string.scan(/(.+):(.+)\n/).map {|k,v| [k.to_sym, v]}.to_h
#=> {:range=>"12", :type=>"default"}
If you're using Rails, there's already the built in method Hash#symbolize_keys
:
string.scan(/(.+):(.+)\n/).to_h.symbolize_keys
#=> {:range=>"12", :type=>"default"}
Upvotes: 5
Reputation: 114178
This would work:
string = "range:12\ntype:default\n"
string.split("\n").each_with_object({}) { |s, h|
k, v = s.split(':')
h[k.to_sym] = v
}
#=> {:range=>"12", :type=>"default"}
Upvotes: 3
Reputation: 51151
If you had spaces before your values:
string = "range: 12\ntype: default\n"
This string would be correct YAML, so you could parse it with Ruby yaml
library:
require 'yaml'
string = "range: 12\ntype: default\n"
@settings = YAML.load(string)
# => {"range"=>12, "type"=>"default"}
So I suggest modifying your settings format a little bit, if you can do it.
Upvotes: 3