From d1a7b01ee532166af7e82e41f889a6734044f620 Mon Sep 17 00:00:00 2001 From: Ben Robinson Date: Tue, 14 Nov 2023 23:07:17 +0000 Subject: [PATCH] Share _obj_diff results between steps of list diff The backtracking pass of the list diff algorithm in `_list_diff_0` was calling `_obj_diff` on pairs of objects that had already been diffed in the forward pass earlier in the `_list_diff` method. This commit saves the `_obj_diff` results from the forward pass and reuses them in the backtracking pass so we don't duplicate the recursive calls. --- jsondiff/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/jsondiff/__init__.py b/jsondiff/__init__.py index 5e86701..5f8eb3b 100644 --- a/jsondiff/__init__.py +++ b/jsondiff/__init__.py @@ -468,12 +468,12 @@ def __init__(self, syntax='compact', load=False, dump=False, marshal=False, for symbol in _all_symbols_ } - def _list_diff_0(self, C, X, Y): + def _list_diff_0(self, C, X, Y, similarity): i, j = len(X), len(Y) r = [] while True: if i > 0 and j > 0: - d, s = self._obj_diff(X[i-1], Y[j-1]) + d, s = similarity[i-1][j-1] if s > 0 and C[i][j] == C[i-1][j-1] + s: r.append((0, d, j-1, s)) i, j = i - 1, j - 1 @@ -494,9 +494,12 @@ def _list_diff(self, X, Y): n = len(Y) # An (m+1) times (n+1) matrix C = [[0 for j in range(n+1)] for i in range(m+1)] + similarity = [[0 for j in range(n)] for i in range(m)] for i in range(1, m+1): for j in range(1, n+1): - _, s = self._obj_diff(X[i-1], Y[j-1]) + child_diff = self._obj_diff(X[i-1], Y[j-1]) + similarity[i-1][j-1] = child_diff + s = child_diff[1] # Following lines are part of the original LCS algorithm # left in the code in case modification turns out to be problematic #if X[i-1] == Y[j-1]: @@ -508,7 +511,7 @@ def _list_diff(self, X, Y): changed = {} tot_s = 0.0 - for sign, value, pos, s in self._list_diff_0(C, X, Y): + for sign, value, pos, s in self._list_diff_0(C, X, Y, similarity): if sign == 1: inserted.append((pos, value)) elif sign == -1: