1
1
package com .softwaremill .diffx .instances
2
2
3
- import com .softwaremill .diffx .Matching .{ MatchingResults , matching }
3
+ import com .softwaremill .diffx .Matching .MatchingResults
4
4
import com .softwaremill .diffx .ObjectMatcher .{IterableEntry , MapEntry }
5
5
import com .softwaremill .diffx ._
6
6
7
+ import scala .annotation .tailrec
7
8
import scala .collection .immutable .{ListMap , ListSet }
8
9
9
10
private [diffx] class DiffForIterable [T , C [W ] <: Iterable [W ]](
@@ -16,12 +17,12 @@ private[diffx] class DiffForIterable[T, C[W] <: Iterable[W]](
16
17
17
18
val leftAsMap = left.toList.lift
18
19
val rightAsMap = right.toList.lift
19
- val leftv2 = ListSet ( keys.map(i => i -> leftAsMap(i)): _* ) .collect { case (k, Some (v)) => MapEntry (k, v) }
20
- val rightv2 = ListSet ( keys.map(i => i -> rightAsMap(i)): _* ) .collect { case (k, Some (v)) => MapEntry (k, v) }
20
+ val lEntries = keys.map(i => i -> leftAsMap(i)).collect { case (k, Some (v)) => MapEntry (k, v) }.toList
21
+ val rEntries = keys.map(i => i -> rightAsMap(i)).collect { case (k, Some (v)) => MapEntry (k, v) }.toList
21
22
22
23
val adjustedMatcher = context.getMatcherOverride[IterableEntry [T ]].getOrElse(matcher)
23
24
val MatchingResults (unMatchedLeftInstances, unMatchedRightInstances, matchedInstances) =
24
- matching(leftv2, rightv2 , adjustedMatcher)
25
+ matchPairs(lEntries, rEntries , adjustedMatcher)
25
26
val leftDiffs = unMatchedLeftInstances
26
27
.diff(unMatchedRightInstances)
27
28
.collectFirst { case MapEntry (k, v) => k -> DiffResultAdditional (v) }
@@ -35,4 +36,32 @@ private[diffx] class DiffForIterable[T, C[W] <: Iterable[W]](
35
36
val diffs = ListMap ((matchedDiffs ++ leftDiffs ++ rightDiffs).map { case (k, v) => k.toString -> v }: _* )
36
37
DiffResultObject (" List" , diffs)
37
38
}
39
+
40
+ private def matchPairs (
41
+ left : List [IterableEntry [T ]],
42
+ right : List [IterableEntry [T ]],
43
+ matcher : ObjectMatcher [IterableEntry [T ]]
44
+ ): MatchingResults [IterableEntry [T ]] = {
45
+ @ tailrec
46
+ def loop (
47
+ left : List [IterableEntry [T ]],
48
+ right : List [IterableEntry [T ]],
49
+ matches : List [(IterableEntry [T ], IterableEntry [T ])],
50
+ leftUnmatched : List [IterableEntry [T ]]
51
+ ): MatchingResults [IterableEntry [T ]] = {
52
+ left match {
53
+ case lHead :: tail =>
54
+ val maybeMatch = right.collectFirst {
55
+ case r if matcher.isSameObject(lHead, r) => lHead -> r
56
+ }
57
+ maybeMatch match {
58
+ case Some (m @ (_, rm)) =>
59
+ loop(tail, right.filterNot(r => r.key == rm.key), matches :+ m, leftUnmatched)
60
+ case None => loop(tail, right, matches, leftUnmatched :+ lHead)
61
+ }
62
+ case Nil => MatchingResults (ListSet (leftUnmatched : _* ), ListSet (right : _* ), ListSet (matches : _* ))
63
+ }
64
+ }
65
+ loop(left, right, List .empty, List .empty)
66
+ }
38
67
}
0 commit comments