Я хотел бы предотвратить возникновение эмиссии тогда и только тогда, когда один и тот же точный элемент был испущен за последние миллисекунды. Я посмотрел на дроссельные заслонки и операторы debounce, но я не уверен, могут ли они помочь мне здесь. Есть ли другой оператор, который я могу использовать, или я могу их каким-то образом создать?
Предотвращение выбросов, если одна и та же эмиссия произошла x миллисекунд назад
Ответ 1
Вы можете сделать это с помощью groupByUntil, чтобы существенно разбить отдельные элементы
o
.groupByUntil(x => x, x => x, x => Observable.timer(1000))
.flatMap(grp => grp.first())
Ответ 2
Вы можете выполнить отметку времени и соединить каждый элемент, а затем проверить свои граничные условия времени и равенства.
randomSource
.timestamp()
.pairwise()
.where(pair => pair[0].timestamp - pair[1].timestamp < limit && pair[0].value === pair[1].value);
Затем примените .select(pair => pair[0].value)
, чтобы вернуть исходный элемент.
Рабочий пример в С# с источником, который генерирует случайные элементы между 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();
}
Вывод:
[email protected]/7/2017 5:00:04 AM +00:00 [email protected]/7/2017 5:00:04 AM +00:00
[email protected]/7/2017 5:00:09 AM +00:00 [email protected]/7/2017 5:00:08 AM +00:00
[email protected]/7/2017 5:00:23 AM +00:00 [email protected]/7/2017 5:00:23 AM +00:00
[email protected]/7/2017 5:00:33 AM +00:00 [email protected]/7/2017 5:00:32 AM +00:00
Ответ 3
Как ваш вопрос не полностью объясняет сценарий, как сравнить следующее испущенное значение с последним испускаемым значением или любыми последними испускаемыми значениями или чем-то еще. Я бы взял общий путь для решения проблемы.
Пример: 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()
(для простого случая), или если вы ищете все последние испускаемые значения, вам нужно сохранить испущенные значения в списке и проверить.
Надеюсь, это поможет.