import 'package:nc_photos/iterator_extension.dart'; import 'package:tuple/tuple.dart'; /// Return the difference between two sorted lists, [a] and [b] /// /// [a] and [b] MUST be sorted in ascending order, otherwise the result is /// undefined. /// /// The first returned list contains items exist in [b] but not [a], the second /// returned list contains items exist in [a] but not [b] Tuple2, List> diffWith( Iterable a, Iterable b, int Function(T a, T b) comparator) { final aIt = a.iterator, bIt = b.iterator; final aMissing = [], bMissing = []; while (true) { if (!aIt.moveNext()) { // no more elements in a bIt.iterate((obj) => aMissing.add(obj)); return Tuple2(aMissing, bMissing); } if (!bIt.moveNext()) { // no more elements in b // needed because aIt has already advanced bMissing.add(aIt.current); aIt.iterate((obj) => bMissing.add(obj)); return Tuple2(aMissing, bMissing); } final result = _diffUntilEqual(aIt, bIt, comparator); aMissing.addAll(result.item1); bMissing.addAll(result.item2); } } Tuple2, List> diff( Iterable a, Iterable b) => diffWith(a, b, Comparable.compare); Tuple2, List> _diffUntilEqual( Iterator aIt, Iterator bIt, int Function(T a, T b) comparator) { final a = aIt.current, b = bIt.current; final diff = comparator(a, b); if (diff < 0) { // a < b if (!aIt.moveNext()) { return Tuple2([b] + bIt.toList(), [a]); } else { final result = _diffUntilEqual(aIt, bIt, comparator); return Tuple2(result.item1, [a] + result.item2); } } else if (diff > 0) { // a > b if (!bIt.moveNext()) { return Tuple2([b], [a] + aIt.toList()); } else { final result = _diffUntilEqual(aIt, bIt, comparator); return Tuple2([b] + result.item1, result.item2); } } else { // a == b return const Tuple2([], []); } }