zip_object_deep()
Creates a nested object from the given keys and values. If the `values` list is not provided, the `keys` list is treated as a list of key-value pairs.
Implementation
Args: keys: A list of keys or key-value pairs. values: A list of values to pair with the keys. Returns: A nested object with the key-value pairs.
Example
zip_object_deep(["a.b.c", "a.b.d"], [1, 2])
Expected output: {"a": {"b": {"c": 1, "d": 2}}}
Alternative usage:
Expected output:
Source Code
def zip_object_deep(
keys: List[Any], values: Optional[List[Any]] = None
) -> Dict[Any, Any]:
result: Dict[Any, Any] = {}
# Build key-value pairs
if values is None:
pairs = keys # type: ignore
else:
pairs = builtins.zip(keys, values) # type: ignore
for k, v in pairs:
# parse path
parts = re.findall(r"[^.\[\]]+", k) # type: ignore
node = result
for i, part in enumerate(parts):
is_last = i == len(parts) - 1
# next part type
if part.isdigit():
idx = int(part)
if not isinstance(node, list):
raise TypeError("Expected list at part %r" % part)
while len(node) <= idx:
node.append({})
if is_last:
node[idx] = v
else:
if not isinstance(node[idx], dict):
node[idx] = {}
node = node[idx]
else:
if is_last:
node[part] = v # type: ignore
else:
# determine if next is index
nxt = parts[i + 1]
if nxt.isdigit():
if part not in node or not isinstance(node[part], list):
node[part] = []
else:
if part not in node or not isinstance(node[part], dict):
node[part] = {}
node = node[part] # type: ignore
return result