Как я могу разобрать строку в хэш? - PullRequest
0 голосов
/ 31 октября 2018

Я пытаюсь разобрать строку в хеш.

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',
 }
}

Может быть, кто-то может помочь, как я могу это сделать. Пока я могу думать только о регулярных выражениях.

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Вот оно. Этот код должен работать с любой структурой.

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}
0 голосов
/ 31 октября 2018

как-то так с регулярным выражением:

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"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...