Introduction

Hello, and welcome back! Are you ready for a new challenge? In this unit, we're stepping up a notch to tackle a complex yet intriguing task. It involves parsing complex strings into Ruby hashes and then updating them, a common requirement in many real-world tasks. So yes, this unit's session is going to be quite pragmatic — just the way you like it!

Task Statement

This task involves transforming a given string into a nested Ruby hash and updating a specific key-value pair within that hash. The input string will take the form "Key1=Value1,Key2=Value2,...". When a part of the value is another key-value string, we create a nested hash.

For example, the string "A1=B1,C1={D1=E1,F1=G1},I1=J1" should be transformed into the following nested hash:

{
  'A1' => 'B1',
  'C1' => {
    'D1' => 'E1',
    'F1' => 'G1'
  },
  'I1' => 'J1'
}

Your Ruby function should parse this string into the above hash, then update the value of the nested key F1 from G1 to some other value, say 'NewValue'. The function should ultimately return the updated hash.

Solution Building: Step 1 - String Parsing

Our first step here will be to parse the string into a nested hash. Before diving into coding, let us understand that simple string splitting methods do not handle hierarchical structures well; hence, our solution needs to account for the nested nature of our text.

As you parse the string, you'll have to read through each character and note its role. Here's a hint: every time the = symbol is encountered, you can infer that the text bit you have on your hands is a key. Further, upon hitting the , symbol, you should gather that you've just finished reading a value. At this stage, it is safe to add the key-value pair you've just read into the hash you're constructing.

The next step calls for special attention to the braces. When you encounter an opening brace {, you should know you are taking a step deeper into the hierarchy. On the other hand, when you encounter a closing brace }, you are taking a step back up.

def parse_string(input_string)
  # Preprocess the input_string: replace commas outside of curly brackets
  preprocessed_string = ""
  balance = 0
  input_string.each_char do |char|
    if char == "{"
      balance += 1
    elsif char == "}"
      balance -= 1
    elsif char == "," && balance == 0
      preprocessed_string += ";"
      next
    end
    preprocessed_string += char
  end

  # Parse to a nested hash
  elements = preprocessed_string.split(";")
  result_hash = {}
  elements.each do |element|
    key, value = element.split("=", 2)
    if value.include?("{")
      # Value is a nested hash
      nested_hash = parse_string(value[1..-2])
      result_hash[key] = nested_hash
    else
      result_hash[key] = value
    end
  end
  result_hash
end
Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal