[英]In Ruby, how can I convert this string format to a hash
The string format is like this字符串格式是这样的
"a.b.c = 1"
"a.b.d = 2"
=> its hash will be
=> {'a'=> {'b' => {'c'=>1, 'd'=>2 } } }
It gets tricky with arrays数组变得棘手
"a.e[0].f = 1"
"a.e[0].g = 2"
"a.e[1].h = 3"
=> its hash will be
=> {'a' => {'e' => [{'f'=>1, 'g'=>2}, {'h'=>3}] } }
I wrote a version which doesn't handle arrays with too many if-else checks我写了一个版本,它不处理带有太多 if-else 检查的数组
def construct
$output[$words[0]] = {} unless $output.has_key?($words[0])
pointer = $output[$words[0]]
$words[1..-2].each do |word|
pointer[word] = {} unless pointer.has_key?(word)
pointer = pointer[word]
end
pointer[$words[-1]] = 1
end
$output = {}
$words = ['a', 'b', 'c']
construct
$words = ['a', 'b', 'd']
construct
p $output
The array version is even worse.阵列版本更糟。 Is there a better way of solving this in Ruby?
在 Ruby 中是否有更好的方法来解决这个问题?
Not as simple as I did expect.没有我想象的那么简单。 Here is what I came up with:
这是我想出的:
class Hash
def hash_merge(other)
update(other) do | key, val_self, val_other |
case val_self
when Hash
val_self.hash_merge val_other
when Array
val_self += [nil] * (val_other.length - val_self.length)
val_self.zip(val_other).map { | a, b | a && b ? a.hash_merge(b) : a || b }
else
# error
end
end
end
end
# parses a string of the form "a.e[1].g = 2" to a hash {"a" => {"e" => [nil , {"g" => 2}]}}
def construct_string(s)
if s =~ /\A\s*(\S+)\s+=\s+(\d+)\z/
s1, s2 = $1, $2
s1.split('.').reverse.inject(s2.to_i) do | hash, name |
if name =~ /\[(\d+)\]\z/
name, idx = $~.pre_match, $1.to_i
array = []
array[idx] = hash
{ name => array }
else
{ name => hash }
end
end
else
# error
end
end
# parses an array of string and merges the resulting hashes
def construct(s)
s.map { | e | construct_string(e) }.inject(&:hash_merge)
end
ins = ["a.e[0].f = 1",
"a.e[0].g = 2",
"a.e[1].h = 3"]
p construct(ins) # {"a"=>{"e"=>[{"f"=>1, "g"=>2}, {"h"=>3}]}}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.