MCPcopy Create free account
hub / github.com/aboutcode-org/scancode-toolkit / match_blocks

Function match_blocks

src/licensedcode/seq.py:107–176  ·  view source on GitHub ↗

Return a list of matching block Match triples describing matching subsequences of `a` in `b` starting from the `a_start` position in `a` up to the `a_end` position in `a`. `b2j` is a mapping of b "high" token ids -> list of positions in b, e.g. a posting list. `len_good` i

(a, b, a_start, a_end, b2j, len_good, matchables=frozenset(), *args, **kwargs)

Source from the content-addressed store, hash-verified

105
106
107def match_blocks(a, b, a_start, a_end, b2j, len_good, matchables=frozenset(), *args, **kwargs):
108 """
109 Return a list of matching block Match triples describing matching
110 subsequences of `a` in `b` starting from the `a_start` position in `a` up to
111 the `a_end` position in `a`.
112
113 `b2j` is a mapping of b "high" token ids -> list of positions in b, e.g. a
114 posting list.
115
116 `len_good` is such that token ids smaller than `len_good` are treated as
117 important, non-junk tokens.
118
119 `matchables` is a set of matchable positions. Positions absent from this set
120 are ignored.
121
122 Each triple is of the form (i, j, n), and means that a[i:i+n] == b[j:j+n].
123 The triples are monotonically increasing in i and in j. It is also
124 guaranteed that adjacent triples never describe adjacent equal blocks.
125 Instead adjacent blocks are merged and collapsed in a single block.
126 """
127
128 # This non-recursive algorithm is using a list as a queue of blocks. We
129 # still need to look at and append partial results to matching_blocks in a
130 # loop. The matches are sorted at the end.
131
132 queue = [(a_start, a_end, 0, len(b))]
133 queue_append = queue.append
134 queue_pop = queue.pop
135 matching_blocks = []
136 matching_blocks_append = matching_blocks.append
137 while queue:
138 alo, ahi, blo, bhi = queue_pop()
139 i, j, k = x = find_longest_match(
140 a, b, alo, ahi, blo, bhi, b2j, len_good, matchables)
141 # a[alo:i] vs b[blo:j] unknown
142 # a[i:i+k] same as b[j:j+k]
143 # a[i+k:ahi] vs b[j+k:bhi] unknown
144 if k: # if k is 0, there was no matching block as the size is 0
145 matching_blocks_append(x)
146 if alo < i and blo < j:
147 # there is unprocessed things remaining to the left
148 queue_append((alo, i, blo, j))
149 if i + k < ahi and j + k < bhi:
150 # there is unprocessed things remaining to the right
151 queue_append((i + k, ahi, j + k, bhi))
152
153 matching_blocks.sort()
154
155 # collapse adjacent blocks
156 i1 = j1 = k1 = 0
157 non_adjacent = []
158 non_adjacent_append = non_adjacent.append
159 for i2, j2, k2 in matching_blocks:
160 # Is this block adjacent to i1, j1, k1?
161 if i1 + k1 == i2 and j1 + k1 == j2:
162 # Yes, so collapse them -- this just increases the length of the
163 # first block by the length of the second, and the first block so
164 # lengthened remains the block to compare against.

Callers 1

match_sequenceFunction · 0.90

Calls 2

find_longest_matchFunction · 0.85
sortMethod · 0.45

Tested by

no test coverage detected