簡體   English   中英

如何將字符串解析為哈希?

[英]How can I parse a string into a hash?

我正在嘗試將字符串解析為哈希。

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

也許有人可以幫助我如何做到這一點。 目前我能想到的唯一方法是正則表達式。

像這樣的正則表達式:

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}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM