Created
May 15, 2019 16:46
-
-
Save PoisonousJohn/7e88a13e8d1eb9f671ce8e19efd262cb to your computer and use it in GitHub Desktop.
deep update for python dicts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import copy | |
import itertools | |
def update_list_by_dict(target: list, value: dict): | |
""" | |
Updates a list using keys from dictionary | |
May be helpful if you want a fuzzy update of a list | |
If key greater than list size, list will be extended | |
If list value is dict, it's deep updated | |
""" | |
for k, v in value.items(): | |
idx = int(k) | |
if idx >= len(target): | |
target.extend(itertools.repeat(None, idx - len(target) + 1)) | |
if isinstance(target[idx], dict) and isinstance(v, dict): | |
deepupdate(target[idx], v) | |
else: | |
target[idx] = v | |
def deepupdate(target: dict, update: dict): | |
"""Deep update target dict with update | |
For each k,v in update: if k doesn't exist in target, it is deep copied from | |
update to target. | |
Nested lists are extend if you update by the list and updated if you update by dictionary | |
""" | |
for k, v in update.items(): | |
curr_val = None | |
if isinstance(target, dict): | |
if k not in target: | |
target[k] = copy.deepcopy(v) | |
curr_val = target[k] | |
if isinstance(curr_val, list): | |
if isinstance(v, list): | |
curr_val.extend(copy.deepcopy(v)) | |
elif isinstance(v, dict): | |
update_list_by_dict(curr_val, v) | |
else: | |
curr_val.extend(v) | |
elif isinstance(curr_val, dict): | |
deepupdate(target[k], v) | |
elif isinstance(curr_val, set): | |
if not k in target: | |
target[k] = v.copy() | |
else: | |
target[k].update(v.copy()) | |
else: | |
target[k] = copy.copy(v) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from .dict_utils import deepupdate, update_list_by_dict | |
def test_update_list_by_dict(): | |
l = [] | |
update_list_by_dict(l, {0: 1, 3: 4}) | |
assert l == [1, None, None, 4] | |
update_list_by_dict(l, {2: 3}) | |
assert l == [1, None, 3, 4] | |
update_list_by_dict(l, {0: 0}) | |
assert l == [0, None, 3, 4] | |
update_list_by_dict(l, {0: {'k1': {'k1.1': 'v1.1', 'k1.2': 'v1.2'}}}) | |
assert l == [{'k1': {'k1.1': 'v1.1', 'k1.2': 'v1.2'}}, None, 3, 4] | |
update_list_by_dict(l, {0: {'k1': {'k1.1': 'v1.1*'}}}) | |
assert l == [{'k1': {'k1.1': 'v1.1*', 'k1.2': 'v1.2'}}, None, 3, 4] | |
def test_deepupdate(): | |
d = {} | |
deepupdate(d, {'k': 'v'}) | |
assert d == {'k': 'v'} | |
deepupdate(d, {'k': {'k1': 1, 'k2': 2}}) | |
assert d == {'k': {'k1': 1, 'k2': 2}} | |
deepupdate(d, {'k': {'k1': 0, }}) | |
assert d == {'k': {'k1': 0, 'k2': 2}} | |
deepupdate(d, {'l': []}) | |
assert d == {'k': {'k1': 0, 'k2': 2}, 'l': []} | |
deepupdate(d, {'l': [1]}) | |
assert d == {'k': {'k1': 0, 'k2': 2}, 'l': [1]} | |
deepupdate(d, {'l': {0: 2}}) | |
assert d == {'k': {'k1': 0, 'k2': 2}, 'l': [2]} | |
deepupdate(d, {'l': {3: 3}}) | |
assert d == {'k': {'k1': 0, 'k2': 2}, 'l': [2, None, None, 3]} | |
deepupdate(d, {'l': {0: {'k1': {'k1.1': 'v1.1', 'k1.2': 'v1.2'}}}}) | |
assert d == {'k': {'k1': 0, 'k2': 2}, 'l': [{'k1': {'k1.1': 'v1.1', 'k1.2': 'v1.2'}}, None, None, 3]} | |
deepupdate(d, {'l': {0: {'k1': {'k1.1': 'v1.1*'}}}}) | |
assert d == {'k': {'k1': 0, 'k2': 2}, 'l': [{'k1': {'k1.1': 'v1.1*', 'k1.2': 'v1.2'}}, None, None, 3]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment