Я пытаюсь преобразовать строку в хеш.
str = "Notifications[0].Open=1
Notifications[0].Body.Message[0]=3455
Notifications[0].Body.Message[1]=2524
Notifications[0].Body.Message[2]=2544
Notifications[0].Body.Message[3]=2452
Notifications[0].Body.Error[0]=2455
Notifications[0].Body.Currency=EUR
Notifications[0].Published=true"
Результат должен выглядеть примерно так:
pairs = {
'Open' = 1,
'Published' => true
'Body' => {
'Message' => [3455, 2524, 2544, 2452],
'Error' => [2455],
'Currency' => 'EUR',
}
}
Может быть, кто-нибудь поможет мне, как мне это сделать. На данный момент я могу думать только о регулярном выражении.
Откуда изначально взялась струна?
Логика непонятна. Откуда взялся 'GBR'
?
@sawa это опечатка
что-то вроде этого с регулярным выражением:
require 'pp'
str = "Notifications[0].Open=1
Notifications[0].Body.Message[0]=3455
Notifications[0].Body.Message[1]=2524
Notifications[0].Body.Message[2]=2544
Notifications[0].Body.Message[3]=2452
Notifications[0].Body.Error[0]=2455
Notifications[0].Body.Currency=EUR
Notifications[0].Published=true"
pairs = {}
pairs['Body'] = {}
values = []
str.scan(/Body\W+(.+)/).flatten.each do |line|
key = line[/\A\w+/]
value = line[/\w+\z/]
if line[/\A\w+\[\d+\]/] || key == 'Error'
values = [] unless pairs['Body'][key]
values << value
value = values
end
pairs['Body'][key] = value
end
str.scan(/\[0\]\.(?!Body.).*/).each do |line|
key = line[/(?!\A)\.(\w+)/, 1]
value = line[/\w+\z/]
if line[/\A\w+\[\d+\]/]
values = [] unless pairs[key]
values << value
value = values
end
pairs[key] = value
end
PP.pp pairs
-
{"Body"=>
{"Message"=>["3455", "2524", "2544", "2452"],
"Error"=>["2455"],
"Currency"=>"EUR"},
"Open"=>"1",
"Published"=>"true"}
Вот. Этот код должен работать с любой структурой.
def parse(path, value, hash)
key, rest = path.split('.', 2)
if rest.nil?
hash[key] = value
else
hash[key] ||= {}
parse(rest, value, hash[key])
end
end
def conv_to_array(hash)
if hash.is_a?(Hash)
hash.each do |key, value|
hash[key] = if value.is_a?(Hash) && value.keys.all? { |k| k !~ /\D/ }
arr = []
value.each do |k, v|
arr[k.to_i] = conv_to_array(v)
end
arr
else
conv_to_array(value)
end
end
hash
else
if hash !~ /\D/
hash.to_i
elsif hash == 'true'
true
elsif hash == 'false'
false
else
hash
end
end
end
str = "Notifications[0].Open=1
Notifications[0].Body.Message[0]=3455
Notifications[0].Body.Message[1]=2524
Notifications[0].Body.Message[2]=2544
Notifications[0].Body.Message[3]=2452
Notifications[0].Body.Error[0]=2455
Notifications[0].Body.Currency=EUR
Notifications[0].Published=true"
str = str.tr('[', '.').tr(']', '')
hash = {}
str.split(' ').each do |chunk|
path, value = chunk.split('=')
parse(path.strip, value.strip, hash)
end
hash = conv_to_array(hash)
hash['Notifications'][0]
# => {"Open"=>1, "Body"=>{"Message"=>[3455, 2524, 2544, 2452], "Error"=>[2455], "Currency"=>"EUR"}, "Published"=>true}
похоже, что этот вывод производит машина - можно ли его отформатировать по-другому?