Skip to content

Commit 3569463

Browse files
committed
⚡ optimize compact method to use deque for improved performance and clarity
1 parent 6035445 commit 3569463

1 file changed

Lines changed: 30 additions & 25 deletions

File tree

src/qs_codec/utils/utils.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import copy
44
import typing as t
5+
from collections import deque
56
from datetime import datetime, timedelta
67
from decimal import Decimal
78
from enum import Enum
@@ -107,31 +108,35 @@ def merge(
107108
}
108109

109110
@staticmethod
110-
def compact(value: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]:
111-
"""Remove all `Undefined` values from a dictionary."""
112-
queue: t.List[t.Dict[str, t.Any]] = [{"obj": {"o": value}, "prop": "o"}]
113-
refs: t.List[t.Any] = []
114-
115-
for i in range(len(queue)): # pylint: disable=C0200
116-
item: t.Mapping[t.Any, t.Any] = queue[i]
117-
obj: t.Mapping[t.Any, t.Any] = item["obj"][item["prop"]]
118-
119-
keys: t.List[t.Any] = list(obj.keys())
120-
for key in keys:
121-
val = obj.get(key)
122-
123-
if (
124-
val is not None
125-
and not isinstance(val, Undefined)
126-
and isinstance(val, t.Mapping)
127-
and val not in refs
128-
):
129-
queue.append({"obj": obj, "prop": key})
130-
refs.append(val)
131-
132-
Utils._remove_undefined_from_map(value)
133-
134-
return value
111+
def compact(root: t.Dict) -> t.Dict:
112+
"""Remove all instances of Undefined from the object."""
113+
stack: deque[t.Union[t.Dict, t.List]] = deque([root])
114+
visited: t.Set[int] = {id(root)}
115+
116+
while stack:
117+
node: t.Union[t.Dict, t.List] = stack.pop()
118+
if isinstance(node, dict):
119+
# copy keys to allow deletion during iteration
120+
for k in list(node.keys()):
121+
v: object = node[k]
122+
if isinstance(v, Undefined): # whatever your sentinel class is
123+
del node[k]
124+
elif isinstance(v, (dict, list)):
125+
if id(v) not in visited:
126+
visited.add(id(v))
127+
stack.append(v)
128+
elif isinstance(node, list):
129+
i: int = 0
130+
while i < len(node):
131+
v = node[i]
132+
if isinstance(v, Undefined):
133+
del node[i]
134+
else:
135+
if isinstance(v, (dict, list)) and id(v) not in visited:
136+
visited.add(id(v))
137+
stack.append(v)
138+
i += 1
139+
return root
135140

136141
@staticmethod
137142
def _remove_undefined_from_list(value: t.List[t.Any]) -> None:

0 commit comments

Comments
 (0)