0

Let's say I have two observables of sorted doubles. I'd like to get the difference between them as an observable. For instance:

           1       2           4        
 left:   ──o───────o───────────o────/
           1    3  4   5
 right:  ──o────o──o───o───/
                   l2          r3   r5
 output: ──────────o───────────o────o─/

The imperative implementation for this is simple: Keep a list of the items on the side that you've still not reached and "emit" the items from the other side.

What is the canonical approach to this in the world of RFP? I'm specifically using RxScala.

Omer van Kloeten
  • 11,800
  • 9
  • 42
  • 53
  • Can you provide a marble diagram showing when the values from the sources are emitted and how that leads to the resulting observable? – Enigmativity Jan 04 '17 at 07:38
  • @Enigmativity I've added a marble diagram. HTH – Omer van Kloeten Jan 04 '17 at 09:49
  • That's a nice marble diagram. How did you make that? I still can't figure out the rule though. Can you explain it please? – Enigmativity Jan 04 '17 at 11:54
  • @Enigmativity it's an artisanal, hand-crafted marble diagram, made from only the finest ASCII characters (aka I made it by hand). the simple explanation is that I want the difference between both observables, sorted and as soon as I can understand that it doesn't exist in either of the sides. – Omer van Kloeten Jan 04 '17 at 19:16
  • You might need to try again - "is that I want the difference between both observables, sorted and as soon as I can understand that it doesn't exist in either of the sides" - that just doesn't make sense to me at all, sorry. – Enigmativity Jan 04 '17 at 23:58
  • @Enigmativity Both sources stream sorted data. I want to know, as soon as it's possible, which elements do not exist on either side. I don't want to wait until the streams are over. It's technically possible to do this and the imperative implementation is simple. – Omer van Kloeten Jan 06 '17 at 14:17

2 Answers2

3

This is how I would do it in rxjava implied that two observables have the same length.

    Observable<Integer> obs1 = Observable.just(1, 2, 4, 6);
    Observable<Integer> obs2 = Observable.just(1, 3, 4, 5);

    obs1.zipWith(obs2, (integer, integer2) -> {
        if (!Objects.equals(integer, integer2)) {
            return Observable.just(integer).concatWith(Observable.just(integer2));
        } else {
            return Observable.empty();
        }
    })
      .flatMap(observable -> observable)
      .sorted()
      .forEach(System.out::println);

EDIT

Another approach would be to use a collection

    Observable<Integer> obs1 = Observable.just(1, 2, 4);
    Observable<Integer> obs2 = Observable.just(1, 3, 4, 5);


    obs1.mergeWith(obs2)
            .sorted()
            .reduce(new ArrayList<Integer>(), (integers, integer) -> {
                if (integers.contains(integer)) {
                    integers.remove(integer);
                } else {
                    integers.add(integer);
                }
                return integers;
            })
            .flatMapIterable(integers -> integers)
            .forEach(System.out::println);
Alexander Perfilyev
  • 6,739
  • 2
  • 17
  • 30
1

I don't think there is much in RxJava to do that symmetric difference "in real time"... Mainly because your starting assumption (the observables are sorted) cannot be made by generic operators, so few will help you with that.

However, you could try to code a custom operator for that purpose, by taking inspiration from sequenceEqual: it internally advances step-by-step between two publishers to perform equality comparison, so that's close to what you want to do.

Simon Baslé
  • 27,105
  • 5
  • 69
  • 70