在Ruby或Rails中转换此字符串的最简洁方法是什么:
"[{one:1, two:2, three:3, four:4},{five:5, six:6}]"
像这样的哈希数组:
[{one:1, two:2, three:3, four:4},{five:5, six:6}]
答案 0 :(得分:4)
这是一行两行:
s.split(/}\s*,\s*{/).
map{|s| Hash[s.scan(/(\w+):(\d+)/).map{|t| proc{|k,v| [k.to_sym, v.to_i]}.call(*t)}]}
NB 我使用split(":")
将键与值分开,但@Cary Swoveland在正则表达式中使用parens的效果更低。然而,他忘记了关键和价值转换。
或者稍微短一些,但是使用数组索引而不是proc
,有些人可能会觉得没有吸引力:
s.split(/}\s*,\s*{/).
map{|s| Hash[s.scan(/(\w+):(\d+)/).map{|t| [t[0].to_sym, t[1].to_i]}]}
<强>结果:强>
=> [{:one=>1, :two=>2, :three=>3, :four=>4}, {:five=>5, :six=>6}]
说明:从头开始。最后一个映射处理"key: value"
形式的字符串列表,并返回[:key, value]
对的列表。 scan
将一串逗号分隔的键值对处理成"key: value"
个字符串列表。最后,初始拆分分隔括号括起来的逗号分隔字符串。
答案 1 :(得分:1)
试试这个:
"[{one:1, two:2, three:3, four:4},{five:5, six:6}]".
split(/\}[ ]*,[ ]*\{/).
map do |h_str|
Hash[
h_str.split(",").map do |kv|
kv.strip.
gsub(/[\[\]\{\}]/, '').
split(":")
end.map do |k, v|
[k.to_sym, v.to_i]
end
]
end
答案 2 :(得分:0)
不漂亮,没有优化,但解决了它。 (虽然这很有趣:))
a = "[{one:1, two:2, three:3, four:4},{five:5, six:6}]"
array = []
a.gsub(/\[|\]/, '').split(/{|}/).map{ |h| h if h.length > 0 && h != ','}.compact.each do |v|
hsh = {}
v.split(',').each do |kv|
arr = kv.split(':')
hsh.merge!({arr.first.split.join.to_sym => arr.last.to_i})
end
array << hsh
end
如果您想让我解释一下,请问。
答案 3 :(得分:0)
你可以这样做。
编辑:我最初是在匆匆忙忙地准备这个答案,在旅途中,借助一台带有不熟悉的操作系统的计算机(Windows)。在@sawa指出错误之后,我开始着手解决它,但是对于这样做的机制感到非常沮丧,所以我放弃并删除了我的答案。现在我又回到了家,我已经做出了我认为必要的更正。
<强>代码强>
def extract_hashes(str)
str.scan(/\[?{(.+?)\}\]?/)
.map { |arr| Hash[arr.first
.scan(/\s*([a-z]+)\s*:\d*(\d+)/)
.map { |f,s| [f.to_sym, s.to_i] }
]
}
end
示例强>
str = "[{one:1, two:2, three:3, four:4},{five:5, six:6}]"
extract_hashes(str)
#=> [{:one=>1, :two=>2, :three=>3, :four=>4}, {:five=>5, :six=>6}]
<强>解释强>
对于上例中的str
,
a = str.scan(/\[?{(.+?)\}\]?/)
#=> [["one:1, two:2, three:3, four:4"], ["five:5, six:6"]]
Enumerable#map首先将a
的第一个元素传递给块并将其分配给块变量:
arr #=> ["one:1, two:2, three:3, four:4"]
然后
b = arr.first
#=> "one:1, two:2, three:3, four:4"
c = b.scan(/\s*([a-z]+)\s*:\d*(\d+)/)
#=> [["one", "1"], ["two", "2"], ["three", "3"], ["four", "4"]]
d = c.map { |f,s| [f.to_sym, s.to_i] }
#=> [[:one, 1], [:two, 2], [:three, 3], [:four, 4]]
e = Hash[d]
#=> {:one=>1, :two=>2, :three=>3, :four=>4}
在Ruby 2.0中,Hash[d]
可以替换为d.to_h
。
因此,a
的第一个元素被映射到e
。
接下来,外部map
将a
的第二个和最后一个元素传递到块中
arr #=> ["five:5, six:6"]
我们获得:
Hash[arr.first
.scan(/\s*([a-z]+)\s*:\d*(\d+)/)
.map { |f,s| [f.to_sym, s.to_i] }
]
#=> {:five=>5, :six=>6}
取代a.last
。
答案 4 :(得分:0)
另一种方法:您的字符串看起来像YAML或JSON -definition:
略微修改的字符串有效:
require 'yaml'
p YAML.load("[ { one: 1, two: 2, three: 3, four: 4}, { five: 5, six: 6 } ]")
#-> [{"one"=>1, "two"=>2, "three"=>3, "four"=>4}, {"five"=>5, "six"=>6}]
有两个问题:
one:1
无法识别,您需要one: 1
)。问题1你需要一个gsub(/:/, ': ')
(我希望你的字符串中没有其他的)
问题2是already a question:Hash[a.map{|(k,v)| [k.to_sym,v]}]
完整示例:
require 'yaml'
input = "[{one:1, two:2, three:3, four:4},{five:5, six:6}]"
input.gsub!(/:/, ': ') #force correct YAML-syntax
p YAML.load(input).map{|a| Hash[a.map{|(k,v)| [k.to_sym,v]}]}
#-> [{:one=>1, :two=>2, :three=>3, :four=>4}, {:five=>5, :six=>6}]
使用json,您需要添加"
,但符号化更容易:
require 'json'
input = '[ { "one":1, "two": 2, "three": 3, "four": 4},{ "five": 5, "six": 6} ]'
p JSON.parse(input)
#-> [{"one"=>1, "two"=>2, "three"=>3, "four"=>4}, {"five"=>5, "six"=>6}]
p JSON.parse(input, :symbolize_names => true)
#-> [{:one=>1, :two=>2, :three=>3, :four=>4}, {:five=>5, :six=>6}]
原始字符串示例:
require 'json'
input = "[{one: 1, two: 2, three:3, four:4},{five:5, six:6}]"
input.gsub!(/([[:alpha:]]+):/, '"\1":')
p JSON.parse(input)
#-> [{"one"=>1, "two"=>2, "three"=>3, "four"=>4}, {"five"=>5, "six"=>6}]
p JSON.parse(input, :symbolize_names => true)
#-> [{:one=>1, :two=>2, :three=>3, :four=>4}, {:five=>5, :six=>6}]