I have a List and want to reduce it to a single value (functional programming term "fold", Ruby term inject
), like
Arrays.asList("a", "b", "c") ... fold ... "a,b,c"
As I am infected with functional programming ideas (Scala), I am looking for an easier/shorter way to code it than
sb = new StringBuilder for ... { append ... } sb.toString
In functional programming, fold (also termed reduce, accumulate, aggregate, compress, or inject) refers to a family of higher-order functions that analyze a recursive data structure and through use of a given combining operation, recombine the results of recursively processing its constituent parts, building up a ...
fold starts folding the list by consecutively applying the folder function to elements in the list starting with the initial value and the first element. If the list is empty, the inital value is returned! The function List. sum is roughly List.
Java is a functional style language and the language like Haskell is a purely functional programming language. Let's understand a few concepts in functional programming: Higher-order functions: In functional programming, functions are to be considered as first-class citizens.
To answer your original question:
public static <A, B> A fold(F<A, F<B, A>> f, A z, Iterable<B> xs) { A p = z; for (B x : xs) p = f.f(p).f(x); return p; }
Where F looks like this:
public interface F<A, B> { public B f(A a); }
As dfa suggested, Functional Java has this implemented, and more.
Example 1:
import fj.F; import static fj.data.List.list; import static fj.pre.Monoid.stringMonoid; import static fj.Function.flip; import static fj.Function.compose; F<String, F<String, String>> sum = stringMonoid.sum(); String abc = list("a", "b", "c").foldLeft1(compose(sum, flip(sum).f(",")));
Example 2:
import static fj.data.List.list; import static fj.pre.Monoid.stringMonoid; ... String abc = stringMonoid.join(list("a", "b", "c"), ",");
Example 3:
import static fj.data.Stream.fromString; import static fj.data.Stream.asString; ... String abc = asString(fromString("abc").intersperse(','));
Given
public static <T,Y> Y fold(Collection<? extends T> list, Injector<T,Y> filter){ for (T item : list){ filter.accept(item); } return filter.getResult(); } public interface Injector<T,Y>{ public void accept(T item); public Y getResult(); }
Then usage just looks like
fold(myArray, new Injector<String,String>(){ private StringBuilder sb = new StringBuilder(); public void Accept(String item){ sb.append(item); } public String getResult() { return sb.toString(); } } );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With