Skip to content

Commit 19f7404

Browse files
committed
new merge algorithm.
1 parent 2441e09 commit 19f7404

File tree

2 files changed

+101
-26
lines changed

2 files changed

+101
-26
lines changed

typed/merge.go

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -174,61 +174,87 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
174174
}
175175
out := make([]interface{}, 0, outLen)
176176

177-
lhsOrder, observedLHS, lhsErrs := w.indexListPathElements(t, lhs)
178-
errs = append(errs, lhsErrs...)
179177
rhsOrder, observedRHS, rhsErrs := w.indexListPathElements(t, rhs)
180178
errs = append(errs, rhsErrs...)
181-
seen := fieldpath.MakePathElementSet(outLen)
179+
lhsOrder, observedLHS, lhsErrs := w.indexListPathElements(t, lhs)
180+
errs = append(errs, lhsErrs...)
181+
182+
sharedOrder := make([]*fieldpath.PathElement, 0, rLen)
183+
for i := range rhsOrder {
184+
pe := &rhsOrder[i]
185+
if _, ok := observedLHS.Get(*pe); ok {
186+
sharedOrder = append(sharedOrder, pe)
187+
}
188+
}
189+
190+
var nextShared *fieldpath.PathElement
191+
if len(sharedOrder) > 0 {
192+
nextShared = sharedOrder[0]
193+
sharedOrder = sharedOrder[1:]
194+
}
182195

183196
lLen, rLen = len(lhsOrder), len(rhsOrder)
184197
for lI, rI := 0, 0; lI < lLen || rI < rLen; {
185-
if lI < lLen && rI < rLen && lhsOrder[lI].Equals(rhsOrder[rI]) {
186-
// merge LHS & RHS items
198+
if lI < lLen && rI < rLen {
187199
pe := lhsOrder[lI]
188-
lChild, _ := observedLHS.Get(pe)
189-
rChild, _ := observedRHS.Get(pe)
190-
mergeOut, errs := w.mergeListItem(t, pe, lChild, rChild)
191-
errs = append(errs, errs...)
192-
if mergeOut != nil {
193-
out = append(out, *mergeOut)
200+
if pe.Equals(rhsOrder[rI]) {
201+
// merge LHS & RHS items
202+
lChild, _ := observedLHS.Get(pe)
203+
rChild, _ := observedRHS.Get(pe)
204+
mergeOut, errs := w.mergeListItem(t, pe, lChild, rChild)
205+
errs = append(errs, errs...)
206+
if mergeOut != nil {
207+
out = append(out, *mergeOut)
208+
}
209+
lI++
210+
rI++
211+
212+
nextShared = nil
213+
if len(sharedOrder) > 0 {
214+
nextShared = sharedOrder[0]
215+
sharedOrder = sharedOrder[1:]
216+
}
217+
continue
194218
}
195-
seen.Insert(pe)
196-
lI++
197-
rI++
198-
continue
199-
}
200-
if lI < lLen {
201-
pe := lhsOrder[lI]
202-
if ok := seen.Has(pe); ok {
203-
// Skip the LHS item because it has already appeared
219+
if _, ok := observedRHS.Get(pe); ok && nextShared != nil && !nextShared.Equals(lhsOrder[lI]) {
220+
// shared item, but not the one we want in this round
204221
lI++
205222
continue
206223
}
224+
}
225+
if lI < lLen {
226+
pe := lhsOrder[lI]
207227
if _, ok := observedRHS.Get(pe); !ok {
208-
// Take the LHS item, without a matching RHS item to merge with
228+
// take LHS item
209229
lChild, _ := observedLHS.Get(pe)
210230
mergeOut, errs := w.mergeListItem(t, pe, lChild, nil)
211231
errs = append(errs, errs...)
212232
if mergeOut != nil {
213233
out = append(out, *mergeOut)
214234
}
215-
seen.Insert(pe)
216235
lI++
217236
continue
218237
}
219238
}
220239
if rI < rLen {
221240
// Take the RHS item, merge with matching LHS item if possible
222241
pe := rhsOrder[rI]
223-
rChild, _ := observedRHS.Get(pe)
224242
lChild, _ := observedLHS.Get(pe) // may be nil
243+
rChild, _ := observedRHS.Get(pe)
225244
mergeOut, errs := w.mergeListItem(t, pe, lChild, rChild)
226245
errs = append(errs, errs...)
227246
if mergeOut != nil {
228247
out = append(out, *mergeOut)
229248
}
230-
seen.Insert(pe)
231249
rI++
250+
// Advance nextShared, if we are merging nextShared.
251+
if nextShared != nil && nextShared.Equals(pe) {
252+
nextShared = nil
253+
if len(sharedOrder) > 0 {
254+
nextShared = sharedOrder[0]
255+
sharedOrder = sharedOrder[1:]
256+
}
257+
}
232258
}
233259
}
234260

typed/merge_test.go

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,54 @@ var mergeCases = []mergeTestCase{{
280280
`{"setStr":[]}`,
281281
`{"setStr":["a","b","c"]}`,
282282
`{"setStr":["a","b","c"]}`,
283+
}, {
284+
`{"setStr":["a","b"]}`,
285+
`{"setStr":["b","a"]}`,
286+
`{"setStr":["b","a"]}`,
287+
}, {
288+
`{"setStr":["a","b","c"]}`,
289+
`{"setStr":["d","e","f"]}`,
290+
`{"setStr":["a","b","c","d","e","f"]}`,
291+
}, {
292+
`{"setStr":["a","b","c"]}`,
293+
`{"setStr":["c","d","e","f"]}`,
294+
`{"setStr":["a","b","c","d","e","f"]}`,
295+
}, {
296+
`{"setStr":["a","b","c","g","f"]}`,
297+
`{"setStr":["c","d","e","f"]}`,
298+
`{"setStr":["a","b","c","g","d","e","f"]}`,
299+
}, {
300+
`{"setStr":["a","b","c"]}`,
301+
`{"setStr":["d","e","f","x","y","z"]}`,
302+
`{"setStr":["a","b","c","d","e","f","x","y","z"]}`,
303+
}, {
304+
`{"setStr":["c","d","e","f"]}`,
305+
`{"setStr":["a","c","e"]}`,
306+
`{"setStr":["a","c","d","e","f"]}`,
307+
}, {
308+
`{"setStr":["a","b","c","x","y","z"]}`,
309+
`{"setStr":["d","e","f"]}`,
310+
`{"setStr":["a","b","c","x","y","z","d","e","f"]}`,
311+
}, {
312+
`{"setStr":["a","b","c","x","y","z"]}`,
313+
`{"setStr":["d","e","f","x","y","z"]}`,
314+
`{"setStr":["a","b","c","d","e","f","x","y","z"]}`,
315+
}, {
316+
`{"setStr":["c","a","g","f"]}`,
317+
`{"setStr":["c","f","a","g"]}`,
318+
`{"setStr":["c","f","a","g"]}`,
319+
}, {
320+
`{"setStr":["a","b","c","d"]}`,
321+
`{"setStr":["d","e","f","a"]}`,
322+
`{"setStr":["b","c","d","e","f","a"]}`,
323+
}, {
324+
`{"setStr":["c","d","e","f","g","h","i","j"]}`,
325+
`{"setStr":["2","h","3","e","4","k","l"]}`,
326+
`{"setStr":["c","d","f","g","2","h","i","j","3","e","4","k","l"]}`,
327+
}, {
328+
`{"setStr":["a","b","c","d","e","f","g","h","i","j"]}`,
329+
`{"setStr":["1","b","2","h","3","e","4","k","l"]}`,
330+
`{"setStr":["a","1","b","c","d","f","g","2","h","i","j","3","e","4","k","l"]}`,
283331
}, {
284332
`{"setBool":[true]}`,
285333
`{"setBool":[false]}`,
@@ -288,7 +336,8 @@ var mergeCases = []mergeTestCase{{
288336
`{"setNumeric":[1,2,3.14159]}`,
289337
`{"setNumeric":[1,2,3]}`,
290338
`{"setNumeric":[1,2,3.14159,3]}`,
291-
}},
339+
},
340+
},
292341
}, {
293342
name: "associative list",
294343
rootTypeName: "myRoot",
@@ -361,7 +410,7 @@ var mergeCases = []mergeTestCase{{
361410
}, {
362411
`{"list":[{"key":"a","id":1},{"key":"b","id":2},{"key":"c","id":3}]}`,
363412
`{"list":[{"key":"c","id":3},{"key":"a","id":1}]}`,
364-
`{"list":[{"key":"c","id":3},{"key":"a","id":1},{"key":"b","id":2}]}`,
413+
`{"list":[{"key":"b","id":2},{"key":"c","id":3},{"key":"a","id":1}]}`,
365414
}, {
366415
`{"atomicList":["a","a","a"]}`,
367416
`{"atomicList":null}`,

0 commit comments

Comments
 (0)