Библиотека потоков Javascript - реализация - PullRequest
0 голосов
/ 07 марта 2019

Java-потоки (или любая другая функциональная библиотека для других языков) очень хороши.

Например, вы можете иметь (js sudo code).

Stream.of([1, 2, 3]).filter(x => x > 2).map(x => x * 5).result(); // [15]

Игнорировать синтаксис иликонкретная реализация - это просто пример.

Теперь у меня проблемы, когда поток немного усложняется.

Например, если мне нужны разные данные на каждом шаге, например:

Stream.of([1,2, 3])
  .map(x => x * 3)
  .zip([4, 5, 6])
  .map(..//here i need the initial array)
  .map(..//here i need the zipped array)
  .total(..//

Как вы видите, в некоторых методах мне нужно последнее вычисленное значение, в некоторых мне нужно начальное значение.

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

map(x => x * 1).map(x => x * 2).map(x => x * 4).map(..//i need the result from 2nd map (x*2)

Это глупый пример, но иллюстрирующий проблему.

Есть ли хорошее решение этой проблемы.

Я думал, что могу сохранить все данные в объектено это приводит к более подробному коду, потому что на каждом шаге я должен устанавливать и получать свойства объекта.

Другой пример: Суммируйте числа: [1, 2, 3, 4] -> 10 Фильтруйте числа выше 2: [1, 2, 3, 4] -> [3, 4] Умножьте каждое числос тСумма: [30, 40]

  Stream.of([1,2,3, 4])
    .sum()
    .filter(// here will be the sum, but i want the initial array and later the sum)
    .map(// here i want the filtered array and the calculated sum)

Спасибо

Ответы [ 2 ]

2 голосов
/ 08 марта 2019

Если вам нужен промежуточный результат, сохраните вычисление:

const initial = Stream.of([1,2,3,4]);
const total   = initial.sum();
const result  = initial.filter(x => x > 2).map(x => x * total);

Приведенный выше пример является наиболее логичным способом написания такого кода. Я не понимаю, почему вы хотите написать код вроде:

Stream.of([1,2,3, 4])
    .sum()
    .filter(/* here will be the sum, but i want the initial array and later the sum */)
    .map(/* here i want the filtered array and the calculated sum */)

Ваш пример сбивает с толку и вводит в заблуждение. Код, написанный в функциональном стиле, не нужно объединять в цепочку.

1 голос
/ 07 марта 2019

Я не знаю для всех языков - я в основном разработчик Java - но в моем понимании нет, нет такой серебряной пули, как та, которую вы ищете.

Метафора Stream , как он используется в библиотеках этих типов, всегда выглядит примерно так

[input stream] --{read elements one by one}--> [calculate] --> [output stream]

Думайте о [input stream] не как о представлении коллекции (хотя в 99% этоиспользовал вот так).Рассматривайте это более широко, например, как сетевой сокет, из которого вы читаете элементы один за другим.И после того, как вы прочитали элемент, он вышел из сетевого сокета, и вы не можете перемотать его назад.

Итак, основной принцип заключается в том, что

  • каждый элемент читается ровно один раз,
  • все процессы [calculate] могут потенциально выполняться параллельно, а
  • процессы [calculate] не имеют побочных эффектов

Этот принцип позволяет оптимизировать библиотекуи распараллелить ваши вычисления внутри, что является основной целью Stream API.

Итак, чтобы ответить на ваш вопрос: если вам нужен расчет, который требует доступа к элементу потока более одного раза, вам нужно сохранитьисходный поток или промежуточный результат в коллекции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...