Interview question
Parse a query filter string
Parses a simple filter expression into a validated dictionary without accepting arbitrary keys.
TL;DR
Parses a simple filter expression into a validated dictionary without accepting arbitrary keys.
Parsing, validation, dictionaries, allowed keys, duplicate handling, and safe API input processing.
Practice the problem like a real interview: restate, reason, implement, and test.
Implement ParseFilters(string? filter, ISet<string> allowedKeys). The input format is key:value,key:value. Trim whitespace, require allowed keys, and let the last duplicate key win.
Next in Coding Practice: Date Range Validation
Input: "status:active, role:admin, status:locked"
Allowed: status, role
Output: { status = locked, role = admin }
ArgumentException.: throw ArgumentException.I would split on commas for segments, then split each segment at the first colon. I would trim key and value, copy the allowed keys into a case-insensitive lookup, and store parsed filters in a case-insensitive dictionary. I would avoid accepting arbitrary keys because API filters often become SQL or query-building input later.
public static IReadOnlyDictionary<string, string> ParseFilters(
string? filter,
ISet<string> allowedKeys)
{
if (allowedKeys is null)
{
throw new ArgumentNullException(nameof(allowedKeys));
}
var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var allowed = new HashSet<string>(allowedKeys, StringComparer.OrdinalIgnoreCase);
if (string.IsNullOrWhiteSpace(filter))
{
return result;
}
foreach (var segment in filter.Split(',', StringSplitOptions.RemoveEmptyEntries))
{
var separatorIndex = segment.IndexOf(':');
if (separatorIndex <= 0 || separatorIndex == segment.Length - 1)
{
throw new ArgumentException($"Invalid filter segment '{segment}'.");
}
var key = segment[..separatorIndex].Trim();
var value = segment[(separatorIndex + 1)..].Trim();
if (!allowed.Contains(key))
{
throw new ArgumentException($"Filter '{key}' is not supported.");
}
result[key] = value;
}
return result;
}
Parsing is O(n) over the filter string plus dictionary lookups for each segment. Space is O(k), where k is the number of distinct parsed keys.
Status and status.Spot a weak answer, missing edge case, or clearer explanation? Send it in.