1

I would like to count objects passing from observable. I know there is a count operator but that can't be used for infinite streams because it waits for completition.

What I want is something like Value -> operator -> Pair(Int, Value). I know there could be a problem with int (or long) overflow and that is maybe a reason nothing like this exists but I still have feeling I've seen something like this before. One can implement this with scan operator but I thought there is a simpler way.

Output would be like:

Observable.just(Event1, Event2, Event3) -> (1, Event1), (2, Event2), (3, Event3)
bio007
  • 893
  • 11
  • 20

2 Answers2

0

Count means a state change. So you can use a "stateful" map instead of an anonymous class. ex:

class Mapper<T, R>(val mapper: (T) -> R) : Function<T, Pair<Int, R>> {
    private var counter = 0
    override fun apply(t: T): Pair<Int, R> {
        return Pair(counter++, mapper(t))
        //or ++counter if you want start from 1 instead of zero
    }
}

//usage

val mapper = Mapper<String, String> { it.toUpperCase() }

Observable.just("a", "b", "c")
          .map(mapper)
          .subscribe {
            Log.d("test logger", it.toString())
           }
Phoenix Wang
  • 2,357
  • 1
  • 11
  • 17
  • Thanks for the possible solution. As I was writing, I know there are ways to implement this behavior but I thought there is ready-made operator for this. But apparently there is none. – bio007 Sep 11 '18 at 06:15
0

You can solve your problem using the RxJava Scan method:

Observable.just("a", "b", "c")
    .scan(new Pair<>(0, ""), (pair, s) -> new Pair<>(pair.first + 1, s))
    .skip(1)

Pair<>(0, "") is your seed value

Lambda (pair, s) -> new Pair<>(pair.first + 1, s) takes the seed value and value emitted by original observable and then produces the next Pair value to be emitted and fed back into the lambda

Skip(1) is needed to avoid emitting the seed value

crimson
  • 56
  • 1
  • 5
  • As I said in my question, I know about the Scan operator. It just feels like it's "too much work" for such a simple need and I was hoping somebody would suggest some operator I was missing. But I'll accept your answer as it's technically correct and there is obviously no such operator :( – bio007 Feb 06 '19 at 08:37
  • If such operator existed, it would be based on 'scan' – crimson Feb 07 '19 at 06:31
  • 'Scan' operator comes from functional programming and it is considered a very basic higher order function operating on lists. The code is very simple and it doesn't seem like it is doing a lot of unnecessary work to me. – crimson Feb 07 '19 at 06:43