如果在x毫秒前发生相同的发射,则防止发射

时间:2017-09-06 22:14:05

标签: rxjs rx-java system.reactive rx-android

当且仅当在最后x毫秒内发出相同的确切项目时,我想防止发生排放。我已经看过油门和去抖操作员,但我不确定他们是否能在这里帮助我。我可以使用另一个操作员,还是可以以某种方式编写它们?

3 个答案:

答案 0 :(得分:4)

您可以使用groupByUntil执行此操作以基本上去除个别项目

o
  .groupByUntil(x => x, x => x, x => Observable.timer(1000))
  .flatMap(grp => grp.first())

答案 1 :(得分:1)

您可以为每个项目添加时间戳并配对,然后检查时间和平等的边界条件。

   randomSource
                .timestamp()
                .pairwise()
                .where(pair => pair[0].timestamp - pair[1].timestamp < limit && pair[0].value === pair[1].value);

然后应用.select(pair => pair[0].value)取回原始项目。

C#中的工作示例,其中一个源生成1到5个随机时间间隔的随机项:

    static IObservable<T[]> Pairwise<T>(this IObservable<T> source)
    {
        source = source.Publish().RefCount();
        return source.Skip(1).Zip(source, (a, b) => new[] { a, b });
    }

    static void Main(string[] args)
    {

        var randomSource =
            Observable.Defer(() => Observable.Timer(TimeSpan.FromSeconds(new Random().NextDouble() * 2))).Repeat().Publish().RefCount().Select(_ => new Random().Next(1, 5));

        var limit = TimeSpan.FromSeconds(1);

        var sameDebounce =
        randomSource
            .Timestamp()
            .Pairwise()
            .Where(pair => pair[0].Timestamp - pair[1].Timestamp < limit && pair[0].Value == pair[1].Value);


        sameDebounce.Subscribe(c => Console.WriteLine("{0} {1}", c[0], c[1]));
        Console.ReadLine();

    }

输出:

2@9/7/2017 5:00:04 AM +00:00 2@9/7/2017 5:00:04 AM +00:00
2@9/7/2017 5:00:09 AM +00:00 2@9/7/2017 5:00:08 AM +00:00
1@9/7/2017 5:00:23 AM +00:00 1@9/7/2017 5:00:23 AM +00:00
2@9/7/2017 5:00:33 AM +00:00 2@9/7/2017 5:00:32 AM +00:00

答案 2 :(得分:1)

由于您的问题并未完全解释方案,例如将下一个发布值与上次发布的值或任何最后发布的值或其他值进行比较。 我会采取一般方式来达成解决方案。

示例位于 RxJava

您可以将timestamp()filter()运算符一起使用,如下所示:

ArrayList<String> list = new ArrayList<>();
        final long[] timeOfSubscribe = {-1};
        final long timeDuration = 2 * 1000; // 2 seconds
        Observable.fromIterable(list)
                .timestamp()
                .filter(item -> item.time() > (timeDuration + timeOfSubscribe[0]) && item.value().equals("your last value"))
                .doOnSubscribe(__ -> timeOfSubscribe[0] = Calendar.getInstance().getTimeInMillis())
                .subscribe();

我想这段代码可以帮助您只需要更改filter()运算符中的值即时比较登录信息。如果您正在寻找最后一个发射值,您可以使用doOnNext()运算符停止上一次发射的值(具有简单的情况),或者如果您要查找所有最后发出的值,则需要将列表中的发射值存储起来并检查。

我希望它有所帮助。