0

My question contains 2 subquestions, therefore it is not limited to java but takes programming paradigms in general into consideration.

I need a Loop which does a usual "forEach" but also provides for each index its previous runs. Let me elaborate.

Let's define:

OBJECTS = a collection of X, where X is just any Type of Object/Data

PREV = the results of the previous iterations as a Collection of Y, Y beeing the result of a single iteration of an X

what "my" suplementalForEach would do is:

OBJECTS.supplementalForEach((PREV, OBJ) -> doStuff(PREV, OBJ))

or as non-stream variant

var PREV = new ArrayList<>();
for(var OBJ : OBJECTS) {
    var result = doStuff(PREV, OBJ);
    PREV.add(result);
}

So in essence in Java this would be a forEach, taking a BiFunction<R, T> instead of Consumer<T>

The Question now is, is there already a programming concept to this idea? If yes, what is it called? And if yes, is there a Java Implementation?

If no i can just implement it myself but this is a curious question of mine. Btw i didn't find anything yet on Google and Stackoverflow to this.

EDIT2: as of now i have implemented these methods, feel free to use them as you please (Keep the comments and references)

/**
 * @author levent.dag
 * https://stackoverflow.com/users/9648047/levent-dag
 * 
 * naming idea with "akuzminykh"
 * https://stackoverflow.com/users/12323248/akuzminykh , 02.06.2020
 * 
 *   <pre>
 * Cumulative Iteration:
 *   the process of iterating with the results of the previous iterations
 *   
 *   definition:
 *   D domain (collection of X)
 *   X &isin; of domain, Data/Object/Value
 *   R results of previous iterations (List<Y>)
 *   
 *   f(R, X) iteration cycle/Function for current X element with the knowledge of previous iteration results R
 *     
 *   
 *   for X &isin; D {
 *     R.add(R, X)
 *   }
 *   
 *   ORDER sensible! use ordered Collections such as Lists and so on.
 *   </pre>
 * @param <X>
 * @param <Y>
 * @param col
 * @param loopIteration
 */
public static <X, Y, LIST extends List<Y>> void cumulativeIteration(final Collection<X> col, final BiFunction<List<Y>, X, Y> loopIteration, Class<Y> clazz) {
    final ArrayList<Y> previous = new ArrayList<>();
    col.forEach(x -> previous.add(loopIteration.apply(previous, x)));
}

/**
 * @author levent.dag
 * https://stackoverflow.com/users/9648047/levent-dag
 * 
 * naming idea with "akuzminykh"
 * https://stackoverflow.com/users/12323248/akuzminykh , 02.06.2020
 * 
 * Same as {@link Essentials#additiveIteration(Collection, BiFunction)}, but the previous results can be mapped.
 * 
 * @param <X>
 * @param <Y>
 * @param col
 * @param loopIteration
 * @param mapper
 */
public static <X, Y> void mappedCumulativeIteration(final Collection<X> col, final BiFunction<Map<String, Y>, X, Y> loopIteration, final Function<X, String> mapper) {
    final Map<String, Y> previous = new LinkedHashMap<>();
    col.forEach(x -> previous.put(mapper.apply(x), loopIteration.apply(previous, x)));
}

additionally as @daniu has pointed out you could achieve this with a collector, if you want to collect the given data.

col.stream().<List<Y>>collect(()->new ArrayList<>(), (pre, current) -> pre.add(loopIteration.apply(pre, current)), List::addAll); 

Or as a standalone Collector

/**
 * @author levent.dag
 * https://stackoverflow.com/users/9648047/levent-dag
 * 
 * naming idea with "akuzminykh"
 * https://stackoverflow.com/users/12323248/akuzminykh , 02.06.2020
 * 
 *   <pre>
 * Cumulative Iteration:
 *   the process of iterating with the results of the previous iterations
 *   
 *   definition:
 *   D domain (collection of X)
 *   X &isin; of domain, Data/Object/Value
 *   R results of previous iterations (List<Y>)
 *   
 *   f(R, X) iteration cycle/Function for current X element with the knowledge of previous iteration results R
 *     
 *   
 *   for X &isin; D {
 *     R.add(R, X)
 *   }
 *   
 *   ORDER sensible! use ordered Collections such as Lists and so on.
 *   </pre>
 *
 * @param <OBJECT>
 * @param <RESULT>
 */
public class CumulativeListCollector<OBJECT, RESULT> implements Collector<OBJECT, List<RESULT>, List<RESULT>> {

    private final BiFunction<List<RESULT>, OBJECT, RESULT> loopIteration;

    public CumulativeListCollector(final BiFunction<List<RESULT>, OBJECT, RESULT> loopIteration) {
        this.loopIteration = loopIteration;
    }

    public static <O,R> CumulativeListCollector<O, R> of(final BiFunction<List<R>, O, R> loopIteration) {
        return new CumulativeListCollector<>(loopIteration);
    }

    @Override
    public Supplier<List<RESULT>> supplier() {
        return ()->new ArrayList<RESULT>();
    }

    @Override
    public BiConsumer<List<RESULT>, OBJECT> accumulator() {
        return (pre, current) -> pre.add(this.loopIteration.apply(pre, current));
    }

    @Override
    public Function<List<RESULT>, List<RESULT>> finisher() {
        return Function.identity();
    }

    @Override
    public BinaryOperator<List<RESULT>> combiner() {
        return (left, right)->{left.addAll(right); return left;};
    }

    @Override
    public Set<Characteristics> characteristics() {
        return Set.of();
    }
}
Levent Dag
  • 162
  • 8
  • 2
    Are you looking for a _name_ for this? – Sweeper Jun 02 '20 at 09:55
  • @Sweeper yes if this concept exists – Levent Dag Jun 02 '20 at 09:55
  • @akuzminykh yes i could do that as i've shown it in the code section, however i would like to know if this concept already exists and if so how it is called. – Levent Dag Jun 02 '20 at 09:56
  • 1
    It doesn't seem so special or clever to me so that it's worth a special *name* ... – akuzminykh Jun 02 '20 at 09:58
  • This reminds me of recursion in Haskell: split the list into the first element and the rest of the elements. Do something with the first element, then recursively call the function to the rest of the elements. – Sweeper Jun 02 '20 at 10:00
  • @akuzminykh yeah you might be right however it would be helpful to have a name for this, because how are you gonna talk about something if it has no name? Explaining a concept over and over again isn't the solution here. With that logic we also might say, why give an Object the name "Table". – Levent Dag Jun 02 '20 at 10:01
  • @LeventDag Then, I guess, what name would you give it? Maybe you can give it a name and then it becomes established, e.g. the *"Levent-for"*. :D – akuzminykh Jun 02 '20 at 10:03
  • @akuzminykh well in that case i would name it either "SuccessiveForEach" because each iteration is the successor and takes its predecessor into consideration. Or SupplementingForEach but i don't know if i like that word. I'm open for naming ideas. – Levent Dag Jun 02 '20 at 10:47
  • @LeventDag Maybe "additive iteration"? Because on each iteration you add to data that is to be used in the next iteration. Maybe something with ["Series"](https://en.wikipedia.org/wiki/Series_(mathematics)), e.g. "series iteration", as well. Anyways, I really doubt there is any already established name for it. – akuzminykh Jun 02 '20 at 11:18
  • @akuzminykh yeah i think "additive iteration" is the most fitting. – Levent Dag Jun 02 '20 at 12:03
  • Does this answer your question? [Is there simplest possible reduce/fold method in java?](https://stackoverflow.com/questions/56384068/is-there-simplest-possible-reduce-fold-method-in-java) – Joe Jun 02 '20 at 12:38
  • @Joe no unfortunately not, A reduction does reduce a collection into a single value, which is not the aim here. So we dont want to accumulate our Values to a single one rather we want to loop each value with the knowledge of its predecessors results – Levent Dag Jun 02 '20 at 12:40
  • 1
    You can easily do this using [Stream#collect(supplier, accumulator, combiner)](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect-java.util.function.Supplier-java.util.function.BiConsumer-java.util.function.BiConsumer-) with a fitting accumulator implementation. – daniu Jun 02 '20 at 12:49
  • 1
    Actually, I think "cumulative iteration" might be the best name. This is from ["Cumulative Sum"](https://mathworld.wolfram.com/CumulativeSum.html) that is the sum of partial sums of a given sequence or [Series](https://en.wikipedia.org/wiki/Series_(mathematics)). On each iteration you are using the cumulatively created list from the last iteration. Damn, that's some sciency stuff. – akuzminykh Jun 02 '20 at 13:05
  • @akuzminykh yeah thats it! i was looking for the word cumulative. So "cumulative iteration"? – Levent Dag Jun 02 '20 at 13:14
  • @daniu mhm so you would suggest a Collector like col.stream().>collect(()->new ArrayList<>(), (pre, current) -> pre.add(loopIteration.apply(pre, current)), List::addAll); I mean yeah, but in essence we are not trying to collect data but thanks for your contribution! – Levent Dag Jun 02 '20 at 13:14
  • @LeventDag Yeah, I think that sound pretty right and seems fitting. – akuzminykh Jun 02 '20 at 13:24
  • @akuzminykh the Edit2 section should contain everything now – Levent Dag Jun 02 '20 at 14:06

0 Answers0