如何将字符串解析为哈希?

时间:2018-10-31 13:21:19

标签: ruby string parsing 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',
 }
}

也许有人可以帮助我实现目标。我目前认为的唯一方法是regexp。

2 个答案:

答案 0 :(得分:0)

使用regexp这样的东西:

public class HomeActivityClass extends AppCompatActivity implements HomeActivityView, View.OnClickListener, BottomNavigationView.OnNavigationItemSelectedListener, ConnectivityReceiver.ConnectivityReceiverListener{

private Cardview openKinMarketPlaceButton;

 @Override
    protected void onCreate(Bundle savedInstanceState){
        setViews();
        openKinMarketPlaceButton.setOnClickListener(this);
}


@Override
    public void setViews() {
        fragmentManager = getSupportFragmentManager();
        homeBottomNavigationView = findViewById(R.id.home_bottom_navigation_view);
        homeToolbarLayout = findViewById(R.id.home_activity_home_toolbar);
        userAvatarImageView = homeToolbarLayout.findViewById(R.id.home_activity_user_profile_image_view);
        openKinMarketPlaceButton = homeToolbarLayout.findViewById(R.id.home_toolbar_open_kin_marketplace_card_view);
        currentKinBalanceTextView = homeToolbarLayout.findViewById(R.id.home_toolbar_current_kin_balance_text_view);
        kinBalanceStatusTextView = homeToolbarLayout.findViewById(R.id.home_toolbar_kin_balance_status_text_view);
        deviceScreenSizeValidation();
    }

@Override
    public void onClick(View v) {
        if (v == openKinMarketPlaceButton){
            homeActivityPresenter.onKinButtonClicked();
        }
    }
}

-

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

答案 1 :(得分:0)

是的。该代码应适用于任何结构。

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}