Process Operations for an In-Memory Key-Value Store
Company: Rbcroyalbank
Role: Machine Learning Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
# Process Operations for an In-Memory Key-Value Store
Implement an in-memory key-value store that supports adding or replacing a value, deleting a key, and querying a key.
```python
def process_operations(operations: list[list[str]]) -> list[str]:
...
```
Each operation has one of these forms:
- `["SET", key, value]`: store `value` under `key`, replacing the previous value if the key already exists.
- `["DELETE", key]`: remove `key` if it exists. Deleting a missing key is a no-op.
- `["GET", key]`: append the current value to the result, or append `"NULL"` if the key is absent.
Return the results of the `GET` operations in encounter order. Keys and values are case-sensitive strings. The literal value `"NULL"` will not appear in a `SET` operation.
## Constraints
- `0 <= len(operations) <= 200_000`
- `1 <= len(key), len(value) <= 100`
- Every operation has the exact arity shown above.
- Aim for expected constant time per operation and linear time overall.
## Examples
```text
Input:
operations = [
["SET", "model", "v1"],
["GET", "model"],
["SET", "model", "v2"],
["GET", "model"],
["DELETE", "model"],
["GET", "model"]
]
Output: ["v1", "v2", "NULL"]
```
```text
Input:
operations = [["DELETE", "missing"], ["GET", "missing"]]
Output: ["NULL"]
```
Quick Answer: Implement a simple in-memory key-value store from a stream of SET, GET, and DELETE operations. This coding exercise checks hash-map updates, replacement and missing-key semantics, ordered query output, and expected constant-time processing at scale.
Implement an in-memory key-value store that is driven by a list of operations.
Write `process_operations(operations)`. Each element of `operations` is a list of
strings describing exactly one command, in one of these three forms:
- `["SET", key, value]` - store `value` under `key`, replacing the previous value
if `key` is already present.
- `["DELETE", key]` - remove `key` from the store if it is present. Deleting a key
that is absent is a no-op, not an error.
- `["GET", key]` - look up `key`. Append its current value to the result list, or
append the sentinel string `"NULL"` if the key is absent.
Return the results of the `GET` operations as a list of strings, in the order the
`GET` operations were encountered. Operations that are not `GET` contribute
nothing to the result, so a run containing no `GET` returns an empty list.
Keys and values are case-sensitive: `"Key"`, `"key"`, and `"KEY"` are three
distinct keys, and a value's case is preserved exactly as it was stored. The
literal value `"NULL"` never appears as the value of a `SET`, so a returned
`"NULL"` unambiguously means "the key was absent"; note that other spellings such
as `"null"` or `"Null"` are ordinary values and must be returned verbatim.
Every operation is guaranteed to be well formed and to have exactly the arity
shown above, so you never have to handle a ragged or unrecognized operation.
Aim for expected constant time per operation and linear time overall.
## Example 1
```text
Input: operations = [["SET", "model", "v1"], ["GET", "model"],
["SET", "model", "v2"], ["GET", "model"],
["DELETE", "model"], ["GET", "model"]]
Output: ["v1", "v2", "NULL"]
```
The first `GET` reads the value stored by the first `SET`. The second `SET`
replaces it, so the second `GET` reads `"v2"`. After the `DELETE` the key is
absent, so the third `GET` yields the sentinel `"NULL"`.
## Example 2
```text
Input: operations = [["DELETE", "missing"], ["GET", "missing"]]
Output: ["NULL"]
```
Deleting the absent key `"missing"` is a no-op, and the following `GET` finds no
value, so it appends `"NULL"`. The result has one entry because the input has
exactly one `GET`.
Constraints
- 0 <= len(operations) <= 200_000
- 1 <= len(key) <= 100
- 1 <= len(value) <= 100
- Each operation is exactly ["SET", key, value] (length 3), ["DELETE", key] (length 2), or ["GET", key] (length 2); no other verb or arity occurs
- Keys and values are case-sensitive strings
- The literal value "NULL" never appears as the value of a SET operation
- The returned list contains exactly one entry per GET operation, in encounter order
Examples
Input: ([['SET', 'model', 'v1'], ['GET', 'model'], ['SET', 'model', 'v2'], ['GET', 'model'], ['DELETE', 'model'], ['GET', 'model']],)
Expected Output: ['v1', 'v2', 'NULL']
Input: ([['DELETE', 'missing'], ['GET', 'missing']],)
Expected Output: ['NULL']
Hints
- A hash map gives you expected O(1) lookup, insertion, and removal, which is what the per-operation target asks for. Pick the language's standard dictionary/map type rather than scanning a list of pairs.
- Only GET appends to the result. Build the result list as you sweep the operations once, in order, so encounter order falls out for free.
- Distinguish "the key is absent" from "the key holds some value". Removing an absent key must be silently ignored, and an absent GET appends the sentinel "NULL" rather than raising or skipping.