Parse Query Parameters Into a Map
Company: Airbnb
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Implement a function that parses the query portion of a GET URL and returns a map from query keys to parsed values.
Input is a string that may start with `?`, followed by query segments separated by `&`.
Rules:
- A normal segment has the form `key=value`.
- Keys are not guaranteed to be unique.
- If a key appears once, store its single parsed value.
- If a key appears multiple times, store all of its parsed values in a list, preserving input order.
- Values may represent one of these types: integer, string, boolean, or list values created by duplicate keys.
- Quoted string values should be returned without the surrounding quotes.
- A segment without `=` that starts with `!`, such as `!isBooleanField`, represents a Boolean flag. Remove the leading `!` and store the key with value `true`.
Example:
Input:
```text
?key1=1&key1="abc"&key2=value1&!isBooleanField
```
Output conceptually:
```text
{
"key1": [1, "abc"],
"key2": "value1",
"isBooleanField": true
}
```
Design the parser and implement the function.
Quick Answer: This question evaluates ability to implement robust string parsing, type inference, and map/list construction for URL query parameters, including handling duplicate keys, quoted strings, and boolean flag syntax.
Implement a function `solution(query)` that parses the query portion of a GET URL and returns a dictionary/map from keys to parsed values. The input is a string that may start with `?`. After removing the optional leading `?`, split the remaining text on `&` and ignore empty segments. Each non-empty segment is guaranteed to be one of these forms: `key=value` or `!key`. For `key=value`, split only on the first `=`. Parse the value using these rules: if it is wrapped in double quotes, return the inner text as a string; otherwise, if it is a valid integer literal with an optional leading `-`, return it as an integer; otherwise return it as a plain string. For `!key`, store the key with the Boolean value `True`. If a key appears only once, store its single parsed value directly. If a key appears multiple times, store all parsed values in a list in the order they appear.
Constraints
- 0 <= len(query) <= 100000
- Each non-empty segment is valid and is either `key=value` or `!key`
- Quoted string values use matching double quotes
- For `key=value`, only the first `=` separates the key from the value
Examples
Input: '?key1=1&key1="abc"&key2=value1&!isBooleanField'
Expected Output: {'key1': [1, 'abc'], 'key2': 'value1', 'isBooleanField': True}
Explanation: The key `key1` appears twice, so its parsed values are collected into a list. `key2` appears once as a plain string, and `!isBooleanField` becomes `True`.
Input: '?'
Expected Output: {}
Explanation: After removing the leading `?`, the query is empty, so the result is an empty dictionary.
Hints
- Strip the optional leading `?`, split on `&`, and process each segment one by one.
- Use a dictionary for storage; when a key repeats, convert its existing value into a list and append the new parsed value.