Как реализовать эффективную фильтрацию списка на RxJS?

У меня есть список игрушек, у каждой игрушки есть свойства. Свойства могут меняться. Есть функция фильтрации, которая может быть сложно и тяжёлой и которая тоже может меняться динамически. Хотелось бы, чтобы перефильтрация происходила лишь тогда, когда меняются свойства, от которых результат фильтрации реально зависит. Я так понимаю, каждое свойство должно быть стримом и надо как-то подписаться на заданные свойства всех игрушек. Как это лучше всего сделать?

У меня пока получилось следующее:
const ToysSource = new Rx.BehaviorSubject( [] )
const Toys = ToysSource.distinctUntilChanged().debounce( 0 )

const FilterSource = new Rx.BehaviorSubject( toy => toy.count > 0  )
const Filter = FilterSource.distinctUntilChanged().debounce( 0 )

const ToysFiltered = Filter
.select( filter => {
	if( !filter ) return Toys
	return Toys.map( toys => toys.filter( filter ) )
} )
.switch()
.distinctUntilChanged()
.debounce( 0 )


Но тут, очевидно, при любом изменении игрушек будет происходить повторная фильтрация.
  • Вопрос задан
  • 2155 просмотров
Пригласить эксперта
Ответы на вопрос 1
Xuxicheta
@Xuxicheta
инженер
Вот вариант.
Принцип в следующем,
1. на каждый ключ фильтра, применяя соответствующую ключу "функцию ключа фильтра", рассчитывается массив из айдишников, которые надо исключить из списка.
2 собираем все эти массивы айдишников и выкидываем их из списка.

При изменении фильтра, каждая функция ключа сравнивается с предыдущей, и если не изменилась, то результат не пересчивается заново.

https://stackblitz.com/edit/rxjs-wxfjxe?file=index.ts

Сравнение функций реализовано через pairwise, т.е. помнит только предыдущий вариант.
Можно развить решение, например разбить объект фильтра на потоки по каждому ключу, добавив туда мемоизацию. Но не сегодня :)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы