ReactiveX: отфильтровывать числа из наблюдаемых, чтобы общее количество никогда не опускалось ниже нуля

Следующий код RxJs отображает числа из входного списка и промежуточную сумму:

let inputs = [10, 10, -30, 10, -30, 50, -25, -30, 10]

let obs$ = Rx.Observable.from(inputs)
let totals$ = obs$.scan((acc, next) => acc + next, 0)
obs$.subscribe(x => console.info('x:', x));
totals$.subscribe(x => console.info("total:", x))

totals$ выдаст: 10, 20, -10, 0, -30 ...

Я хотел бы как-то преобразовать наблюдаемую obs$, чтобы полученный totals$ никогда не выдавал отрицательное число.

То есть, в этом случае должны быть отфильтрованы как первый, так и последний "-30":

otherObs$: 10, 10, 10, -30, 50, -25, 10

totals$: 10, 20, 30, 0, 50, 25, 35

edit: Обратите внимание, что меня интересует измененная наблюдаемая otherObs$, то есть последовательность исходных входных чисел с некоторыми отфильтрованными (obs$ на самом деле будет содержать больше данных, поэтому мне действительно нужны исходные элементы; "значение" просто ключ для фильтрации). Здесь totals$ - это Только, чтобы показать, что происходит.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
44
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете легко добиться этого, включив эту логику в свою функцию уменьшения, также известную как внутри .scan():

let total$ = obs$.scan((acc, next) => {
    if (acc + next < 0) { //less than zero, don't take in the current number
        return acc;
    }
    return acc + next; //all is good, continue to add next
}, 0)

Или даже в один лайнер:

let totals$ = obs$.scan((acc, next) => (acc + next < 0 ? acc : acc + next), 0)

Если вы хотите сохранить каждое значение и по-прежнему проверять сумму, тогда нет другого выбора, кроме как сохранить каждую последовательность в массиве:

let other$ =
    obs$
        .scan((acc, next) => {
            let sum = acc.reduce((a,b)=>a+b);
            if ((sum+next)<0){
                return acc; // less than zero, return current arrray
            }
            return  acc.push(next); //greater or equal to zero, add current item to array
        }, [...0])
        .switchMap(array => Observable.from(array))

К сожалению, меня интересуют числа из исходной последовательности, а не общее количество. Я хочу получить наблюдаемое, так что когда я применяю свое исходное сокращение totals$, я получаю неотрицательные

matejcik 16.08.2018 11:41
Ответ принят как подходящий

Основываясь на идеях @ CozyAzure, я придумал лучший ответ. Мне просто нужно сохранить в редукторе больше состояний: исходное значение, накопленный итог и было ли это значение добавлено к общему количеству или нет.

let other$ = obs$
  .scan(({value, total, valid}, next) => {
     if (total + next < 0)
       return { value: next, total: total, valid: false }
     else
       return { value: next, total: total + next, valid: true }
  }, { value: undefined, total: 0, valid: false })
  .filter(x => x.valid)
  .map(x => x.value)

Таким образом, я могу отфильтровать значения, которые были добавлены нет, и вернуть исходные значения, которые были.

Другие вопросы по теме