net.ericaro.neoitertools.Itertools Maven / Gradle / Ivy
package net.ericaro.neoitertools;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import net.ericaro.neoitertools.generators.ChainGenerator;
import net.ericaro.neoitertools.generators.CharSequenceGenerator;
import net.ericaro.neoitertools.generators.CycleGenerator;
import net.ericaro.neoitertools.generators.DropWhileGenerator;
import net.ericaro.neoitertools.generators.EmptyGenerator;
import net.ericaro.neoitertools.generators.EnumerateGenerator;
import net.ericaro.neoitertools.generators.FilterGenerator;
import net.ericaro.neoitertools.generators.GeneratorIterator;
import net.ericaro.neoitertools.generators.GenericArrayGenerator;
import net.ericaro.neoitertools.generators.GroupByGenerator;
import net.ericaro.neoitertools.generators.IteratorGenerator;
import net.ericaro.neoitertools.generators.MapGenerator;
import net.ericaro.neoitertools.generators.RangeGenerator;
import net.ericaro.neoitertools.generators.RepeatGenerator;
import net.ericaro.neoitertools.generators.YieldGenerator;
import net.ericaro.neoitertools.generators.SliceGenerator;
import net.ericaro.neoitertools.generators.TakeWhileGenerator;
import net.ericaro.neoitertools.generators.TeeGeneratorFactory;
import net.ericaro.neoitertools.generators.YieldThread;
import net.ericaro.neoitertools.generators.ZipGenerator;
import net.ericaro.neoitertools.generators.ZipPairGenerator;
import net.ericaro.neoitertools.generators.combinatorics.Combinatorics;
import net.ericaro.neoitertools.generators.primitives.BooleanGenerator;
import net.ericaro.neoitertools.generators.primitives.ByteGenerator;
import net.ericaro.neoitertools.generators.primitives.CharacterGenerator;
import net.ericaro.neoitertools.generators.primitives.DoubleGenerator;
import net.ericaro.neoitertools.generators.primitives.FloatGenerator;
import net.ericaro.neoitertools.generators.primitives.IntegerGenerator;
import net.ericaro.neoitertools.generators.primitives.LongGenerator;
import net.ericaro.neoitertools.generators.primitives.ShortGenerator;
/**
*
* This module implements a number of generator building blocks inspired by constructs from the Python programming languages. Each has been recast in a form
* suitable for Java.
*
*
* The module standardizes a core set of fast, memory efficient tools that are useful by themselves or in combination. Standardization helps avoid the
* readability and reliability problems which arise when many different individuals create their own slightly varying implementations, each with their own
* quirks and naming conventions.
*
*
* The tools are designed to combine readily with one another. This makes it easy to construct more specialized tools succinctly and efficiently in pure Java.
*
*
* @author eric
* @see Itertools's wiki page
* @see neoitertools site
*/
public class Itertools {
/**
*
* Return True if all elements of the generator are evaluated to true with the Predicate (or if the generator is empty).
*
*
* @param
* type of generator elements
* @param generator
* @param predicate
* @see Itertools's wiki page
* @see neoitertools site
* @return true|false
*/
public static boolean all(Generator generator, Lambda super T, Boolean> predicate) {
try {
while (predicate.map(generator.next())) {
}
return false;
} catch (NoSuchElementException e) {
return true;
}
}
/**
*
* Return True if any element of the generator is mapped to true. If the generator is empty, return False.
*
*
* @param generator
* @param predicate
* @return true|false
* @see Itertools's wiki page
* @see neoitertools site
*/
public static boolean any(Generator generator, Lambda super T, Boolean> predicate) {
try {
while (!predicate.map(generator.next())) {
}
return true;
} catch (NoSuchElementException e) {
return false;
}
}
/**
*
* Make an generator that returns elements from the first iterable until it is exhausted, then proceeds to the next iterable, until all of the iterables are
* exhausted. Used for treating consecutive sequences as a single sequence.
*
*
* We do not use varargs due to an inner flaw in varargs that make them hard/impossible to combine with generics
*
*
* @param generators
* a generator over generators
* @return a new generator that chain together all the above generators
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator chain(Generator> generators) {
return new ChainGenerator(generators);
}
/**
*
* Chain together two generators.
*
*
* @param generators
* any generators
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator chain(Generator... generators) {
return chain(iter(generators));
}
/**
*
* Return r
length subsequences of elements from the input generator.
*
*
* Combinations are emitted in lexicographic sort order. So, if the input generator is sorted, the combination tuples will be produced in sorted order.
*
*
* Elements are treated as unique based on their position, not on their value. So if the input elements are unique, there will be no repeat values in each
* combination.
*
*
* @param generator
* @param r
* @return generator over combinations as list
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator> combinations(Generator generator, int r) {
List list = list(generator);
return Combinatorics.applied(list, Combinatorics.combinations(list.size(), r));
}
/**
*
* Make a generator that returns all the consecutive integers starting with 0.
*
*
* @see Itertools#count(int)
* @return a count generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator count() {
return count(0);
}
/**
*
* Make an generator that returns consecutive integers starting with n.
*
*
* @param n
* the first integer returned by this generator
* @return a count generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator count(final int n) {
return new RangeGenerator(n, Integer.MAX_VALUE);
}
/**
*
* Make an generator returning elements from the generator and saving a copy of each. When the generator is exhausted, return elements from the saved copy.
* Repeats indefinitely.
*
*
* @param generator
* the source generator
* @return an generator returning elements from the generator over and over
* again.
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator cycle(Generator generator) {
return new CycleGenerator(generator);
}
/**
*
* Make an generator that drops elements from the generator as long as the predicate is true. Afterwards, returns every element.
*
*
* Note, the generator does not produce any output until the predicate first becomes false, so it may have a lengthy start-up time.
*
*
* @param
* @param generator
* @param predicate
* @return generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator dropwhile(Lambda predicate, Generator generator) {
return new DropWhileGenerator(predicate, generator);
}
/**
*
* Return an {@link Generator} of Index object.
*
*
* The next() method of the generator returned by enumerate() returns an Index containing a count (from start which defaults to 0) and the corresponding
* value obtained from iterating over generator.
*
*
* enumerate() is useful for obtaining an indexed series: (0, seq[0]), (1, seq[1]), (2, seq[2]), .... For example:
*
*
* for (Index index : enumerate(seasons))
* System.out.println(index.i + " " + index.value);
*
*
* gives:
*
*
* 0 Spring
* 1 Summer
* 2 Fall
* 3 Winter
*
*
*
*
* @param generator
* the source generator to enumerate
* @return a generator of index
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator> enumerate(final Generator generator) {
return new EnumerateGenerator(generator);
}
/**
*
* Make an generator that filters elements from generator returning only those for which the predicate is True.
*
*
* @param predicate
* @param generator
* @return a filtered generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator filter(Lambda predicate, Generator generator) {
return new FilterGenerator(predicate, generator);
}
/**
*
* Make an generator that filters elements from generator returning only those for which the predicate is False.
*
*
* @param predicate
* @param generator
* @return a filtered generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator filterfalse(final Lambda predicate, final Generator generator) {
return new FilterGenerator(predicate, generator, true);
}
/**
*
* Make an generator that returns consecutive keys and groups from the source generator.
*
*
* The key is a function computing a key value for each element. Generally, the generator needs to already be sorted on the same key function.
*
*
* The operation of groupby() is similar to the uniq filter in Unix. It generates a break or new group every time the value of the key function changes
* (which is why it is usually necessary to have sorted the data using the same key function). That behavior differs from SQL’s GROUP BY which aggregates
* common elements regardless of their input order. The returned group is itself an generator that shares the underlying generator with groupby(). Because
* the source is shared, when the groupby() object is advanced, the previous group is no longer visible. So, if that data is needed later, it should be
* stored as a list.
*
*
* @param generator
* the source generator
* @param key
* the key mapper
* @return an generator that returns consecutive keys and groups from the
* source generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator>> groupby(Generator generator, Lambda key) {
return new GroupByGenerator(generator, key);
}
/** Return the identity Lambda function.
*
* @param any type
*/
public static Lambda identity() {
return new Lambda() {
public T map(T arg) {
return arg;
}
};
}
/**
*
* Turn a {@link Generator} into an {@link Iterable}.
*
* A much required function to use the java foreach statement.
*
*
* for (int i : in(range(12)))
* System.out.println(i);
*
*
* @param generator
* the source generator
* @return a iterable fully equivalent to the generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Iterable in(final Generator generator) {
return new Iterable() {
public Iterator iterator() {
return new GeneratorIterator(generator);
}
};
}
/**
* Turns any boolean[] array into a generator
*
* @param array
* @return a Generator over array
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(boolean[] array) {
return new BooleanGenerator(array);
}
/**
* Turns any byte[] array into a generator
*
* @param array
* @return a Generator over array
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(byte[] array) {
return new ByteGenerator(array);
}
/**
* Turns any char[] array into a generator
*
* @param array
* @return a Generator over array
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(char[] array) {
return new CharacterGenerator(array);
}
/**
* Turns a {@link CharSequence} into an {@link Generator}
*
* @param seq
* any {@link CharSequence}
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(final CharSequence seq) {
return new CharSequenceGenerator(seq);
}
/**
* Turns any double[] array into a generator
*
* @param array
* @return a Generator over array
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(double[] array) {
return new DoubleGenerator(array);
}
/**
* Turns any float[] array into a generator
*
* @param array
* @return a Generator over array
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(float[] array) {
return new FloatGenerator(array);
}
/**
* Turns any int[] array into a generator
*
* @param array
* @return a Generator over array
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(int[] array) {
return new IntegerGenerator(array);
}
/**
* Turns any long[] array into a generator
*
* @param array
* @return a Generator over array
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(long[] array) {
return new LongGenerator(array);
}
/**
* Turns any short[] array into a generator
*
* @param array
* @return a Generator over array
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(short[] array) {
return new ShortGenerator(array);
}
/**
* Turns any object array into an Generator
*
* @param t
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(final T[] t) {
return new GenericArrayGenerator(t);
}
/**
* Turn any {@link Iterable} into a {@link Generator}
*
* @param iterable
* @return a generator over the iterable
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(Iterable iterable) {
return iter(iterable.iterator());
}
/**
* Turn any {@link Iterator} into a {@link Generator}
*
* @param iterator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(Iterator iterator) {
return new IteratorGenerator(iterator);
}
/**
* Turns a Yield generator into a standard Generator.
*
* @param yield a Yield generator statement
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator iter(Yield yield) {
return new YieldGenerator(yield);
}
/**
* Creates a {@link List} from a {@link Generator}
*
* @param generator
* @return a java modifiable List
* @see Itertools's wiki page
* @see neoitertools site
*/
public static List list(Generator generator) {
List list = new LinkedList();
try {
while (true)
list.add(generator.next());
} catch (NoSuchElementException e) {
}
return list;
}
/**
* Creates a list from a generator, of size max
*
* @param generator
* @param max
* maximum size of the list
* @see Itertools's wiki page
* @see neoitertools site
*/
public static List list(Generator generator, int max) {
List list = new LinkedList();
try {
int i = 0;
while (i < max) {
list.add(generator.next());
i++;
}
} catch (NoSuchElementException e) {
}
return list;
}
/**
* Apply {@link Lambda} to every item of sequence
and return a {@link Generator} of the results.
*
* @param mapper
* @param sequence
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator map(final Lambda super T, K> mapper, final Generator sequence) {
return new MapGenerator(mapper, sequence);
}
/**
*
* Return successive full length permutations of elements in the generator.
*
*
* Permutations are emitted in lexicographic sort order. So, if the input iterable is sorted, the permutation list will be produced in sorted order.
*
*
* Elements are treated as unique based on their position, not on their value. So if the input elements are unique, there will be no repeat values in each
* permutation.
*
*
* @param generator
* @return generator of permuted list
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator> permutations(Generator generator) {
List list = list(generator);
return Combinatorics.applied(list, Combinatorics.permutations(list.size()));
}
/**
*
* Return successive r-length permutations of elements in the generator.
*
*
* Permutations are emitted in lexicographic sort order. So, if the input iterable is sorted, the permutation list will be produced in sorted order.
*
*
* Elements are treated as unique based on their position, not on their value. So if the input elements are unique, there will be no repeat values in each
* permutation.
*
*
* @param generator
* @param r
* @return a generator of r-sized permutations
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator> permutations(Generator generator, int r) {
List list = list(generator);
return Combinatorics.applied(list, Combinatorics.sublists(list.size(), r));
}
/**
* Cartesian product of input sequences.
*
* @param generators
* a generator of Generators
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator> product(Generator> generators) {
return product(generators, 1);
}
/**
*
* Cartesian product of input sequences.
*
*
* repeat simulate the repetition of the input sequence.
*
*
* @param generators
* a generator of Generators
* @param repeat
* @return a generator of cartesian product items
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator> product(Generator> generators, int repeat) {
if (repeat == 0)
return new EmptyGenerator>();
List> list = new LinkedList>();
// store all values (required for a product
for (Generator g : in(generators))
list.add(list(g));
// generate length array: length = len(lists)
// [ len( lists[i%length]) for i in range( length ) ]
// or for more fun
// map( len, list*repeat )
// note that I don't use neoitertools to implement it to avoid bug
// propagations
// and that I should also provide a bunch of Lambda object for every
// function in itertools (and more (like len )
int[] lengths = new int[list.size() * repeat];
for (int i = 0; i < lengths.length; i++)
lengths[i] = list.get(i % list.size()).size();
return Combinatorics.selected(list, Combinatorics.product(lengths));
}
/**
* Equivalent to
*
*
* range(0, end, 1)
*
*
* @see Itertools#range(int, int, int)
* @param end
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator range(final int end) {
return range(0, end, 1);
}
/**
* equivalent to
*
*
* range(start, end, 1)
*
*
* @see Itertools#range(int, int, int)
* @param start
* @param end
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator range(int start, int end) {
return range(start, end, 1);
}
/**
*
* This is a versatile function to create generator containing arithmetic progressions.
*
*
* It is most often used in for loops. The full form returns an generator over Integers [start, start + step, start + 2 * step, ...].
*
* - If step is positive, the last element is the largest start + i * step less than stop;
* - if step is negative, the last element is the smallest start + i * step greater than stop.
* - step must not be zero (or else InvalidParameterException is raised).
*
*
* Example:
*
*
* range(0, 30, 5);
*
*
* gives
*
*
* [0, 5, 10, 15, 20, 25]
*
*
*
* range(0, 10, 3);
*
*
* gives
*
*
* [0, 3, 6, 9];
*
*
*
* range(0, -10, -1);
*
*
* gives
*
*
* [0, -1, -2, -3, -4, -5, -6, -7, -8, -9];
*
*
*
*
* @param start
* @param end
* @param step
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator range(final int start, final int end, final int step) throws InvalidParameterException {
return new RangeGenerator(start, end, step);
}
/**
* Equivalent to reduce(operator, generator, null);
*
* @param
* @param operator
* @param generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static T reduce(Operator operator, Generator generator) {
return reduce(operator, generator, null);
}
/**
*
* Apply function of two arguments cumulatively to the items of generator, from left to right, so as to reduce the generator to a single value.
*
*
* For example,
*
*
* Operator<Integer> iadd = new Operator<Integer>() {
* public Integer operate(Integer t1, Integer t2) {
* return t1 + t2;
* }
* };
* Integer res = reduce(iadd, range(1, 6), 0);
*
*
* calculates
*
*
* ((((1 + 2) + 3) + 4) + 5)
*
*
*
* The left argument, x, is the accumulated value and the right argument, y,
* is the update value from the generator. If the initializer is not null,
* it is placed before the items of the generator in the calculation, and
* serves as a default when the iterable is empty. If initializer is null
* and generator contains only one item, the first item is returned.
*
* @param operator
* @param generator
* @param initializer
* @return all items reduced to a single one
* @see Itertools's wiki page
* @see neoitertools site
*/
public static T reduce(Operator operator, Generator generator, T initializer) {
try {
if (initializer == null)
initializer = generator.next();
} catch (NoSuchElementException e) {
return initializer;
}
try {
while (true)
initializer = operator.operate(initializer, generator.next());
} catch (NoSuchElementException e) {
}
return initializer;
}
/**
*
* Make an generator that returns object over and over again.
*
*
* Runs indefinitely Used as argument to map() for invariant function parameters. Also used with zip() to create constant fields in a tuple record.
*
*
* @param object
* @return an generator that returns object over and over again.
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator repeat(T object) {
return new RepeatGenerator(object);
}
/**
*
* Make an generator that returns object times
times.
*
*
* Runs indefinitely unless the times argument is specified. Used as argument to imap() for invariant function parameters. Also used with izip() to create
* constant fields in a tuple record.
*
*
* @param object
* @param times
* number of times the object is returned
* @return an generator that returns object over and over again.
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator repeat(T object, int times) {
return new RepeatGenerator(object, times);
}
/**
*
* Return a reverse generator.
*
*
* The whole generator is stored, so be careful when used.
*
*
* @param generator
* the source generator
* @return a generator that returns values in the reverse order
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator reversed(Generator generator) {
List list = list(generator);
Collections.reverse(list);
return iter(list);
}
/**
* equivalent to {@link Itertools#slice}(0, stop, 1);
*
* @param generator
* source generator
* @param stop
* last included index
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator slice(final Generator generator, final int stop) {
return new SliceGenerator(generator, 0, stop, 1);
}
/**
* equivalent to {@link Itertools#slice}(start, stop, 1);
*
* @param generator
* source generator
* @param start
* first included index
* @param stop
* last included index
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator slice(final Generator generator, final int start, final int stop) {
return slice(generator, start, stop, 1);
}
/**
*
* Make an generator that returns selected elements from the generator.
*
*
* If start is non-zero, then elements from the generator are skipped until start is reached. Afterward, elements are returned consecutively unless step is
* set higher than one which results in items being skipped. It stops at the specified position. slice() does not support negative values for start, stop,
* or step.
*
*
* @param generator
* source generator
* @param start
* first included index
* @param stop
* last included index
* @param step
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator slice(final Generator generator, final int start, final int stop, final int step) {
return new SliceGenerator(generator, start, stop, step);
}
/**
* Returns a sorted Generator in natural ascending order of T.
*
* @param
* @param generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static > Generator sorted(Generator generator) {
List list = list(generator);
Collections.sort(list);
return iter(list);
}
/**
*
* Return a new sorted generator from the items in generator.
*
*
* cmp
specifies a custom Comparator of K. key specifies a {@link Lambda} that is used to extract a comparison key (K) from each generator
* element. reverse is a boolean value. If set to True, then the list elements are sorted as if each comparison were reversed.
*
*
* @param
* Type of items
* @param
* Type of the key used to filter
* @param generator
* source generator
* @param key
* key extraction function
* @param reverse
* if true the the comparison is used in reverse order
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator sorted(Generator generator, final Comparator super K> cmp, final Lambda super T, K> key, final boolean reverse) {
// maps T into (K,T) to perform the sort
Lambda> valueToKeyValue = new Lambda>() {
public Pair map(T arg) {
return new Pair(key.map(arg), arg);
}
};
// Adversely maps (K,T) into T
Lambda, T> keyValueToValue = new Lambda, T>() {
public T map(Pair arg) {
return arg.f1;
}
};
// use comparator of K to compare (K,T)
Comparator> keyComparator = new Comparator>() {
public int compare(Pair o1, Pair o2) {
return (reverse ? -1 : 1) * cmp.compare(o1.f0, o2.f0);
}
};
List> list = list(map(valueToKeyValue, generator));
Collections.sort(list, keyComparator);
return map(keyValueToValue, iter(list));
}
/**
* Return a new sorted generator from the items in generator. the comparator
* is used to sort the generator.
*
* @param
* @param generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator sorted(Generator generator, Comparator super T> cmp) {
List list = list(generator);
Collections.sort(list, cmp);
return iter(list);
}
/**
* Return a new sorted generator from the items in generator. the Key Lambda
* is used to extract a key from T, and that key natural order is used to
* sort the whole generator.
*
* @param
* Type of items
* @param
* Type of the key used to filter
* @param generator
* source generator
* @param key
* key extraction function
* @param reverse
* if true the the comparison is used in reverse order
* @see Itertools's wiki page
* @see neoitertools site
*/
public static > Generator sorted(Generator generator, final Lambda key, final boolean reverse) {
return sorted(generator, new Comparator() {
public int compare(K o1, K o2) {
return o1.compareTo(o2);
}
}, key, reverse);
}
/**
* Turn any Generator of Character into a String
*
* @param chars
* @see Itertools's wiki page
* @see neoitertools site
*/
public static String string(Generator chars) {
return stringBuilder(chars).toString();
}
/**
* Turn any Generator of Character into a StringBuilder
*
* @param chars
* @see Itertools's wiki page
* @see neoitertools site
*/
public static StringBuilder stringBuilder(Generator chars) {
StringBuilder sb = new StringBuilder();
try {
while (true)
sb.append(chars.next().charValue());
} catch (NoSuchElementException e) {
}
return sb;
}
/**
* Make an generator that returns elements from the generator as long as the
* predicate is true.
*
* @param generator
* the source generator
* @param predicate
* test function
* @return an generator that returns elements from the generator as long as
* the predicate is true.
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator takewhile(final Generator generator, final Lambda super T, Boolean> predicate) {
return new TakeWhileGenerator(predicate, generator);
}
/**
* Return n independent generators from a single iterable.
*
* @param generator
* the source generator
* @param n
* number of independent generators
* @return an unmodifiable list of generators.
* @see Itertools's wiki page
* @see neoitertools site
*/
public static List> tee(Generator generator, int n) {
// create the generator provider
List> list = new ArrayList>(n);
TeeGeneratorFactory factory = new TeeGeneratorFactory(generator);
for (int i = 0; i < n; i++)
list.add(factory.newInstance());
return list;
}
/**
* Turns any Generator into a "tuple", here an unmodifiable {@link List}
*
* @param generator
* @return a tuple extracted from a generator
* @see Itertools's wiki page
* @see neoitertools site
*/
public static List tuple(Generator generator) {
return Collections.unmodifiableList(list(generator));
}
/**
* Causes the generate method to stop, and make the t
value
* returned by the associated next
method.
*
* @param t
* @see Yield protocol
* @see Itertools's wiki page
* @see neoitertools site
*/
public static R yield(T t) {
YieldThread thread = (YieldThread) Thread.currentThread();
return thread.yield(t);
}
/**
*
* This function returns an {@link Generator} of tuple (unmodifiable List) , where the i-th couple contains the i-th element from each of the argument
* generators.
*
*
* The returned generator is truncated in length to the length of the shortest argument sequence.
*
*
* Due to static typing of java, it is not possible to provide a generic length of generator and at the same time provide mixed-type tuples, therefore every
* generator must be of type T
. To have two-mixed type use {@link Itertools#zip(Generator, Generator)}
*
*
* @param generators
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator> zip(Generator> generators) {
final List> generatorList = list(generators);
return new ZipGenerator(generatorList);
}
/**
*
* This function returns an {@link Generator} of {@link Pair}s, where the i-th pair contains the i-th element from each of the argument generators.
*
*
* The returned generator is truncated in length to the length of the shortest argument sequence. Due to static typing of java, it is not possible to
* provide a generic length of generator and at the same time provide mixed-type tuples.
*
*
* @param generator1
* @param generator2
* @see Itertools's wiki page
* @see neoitertools site
*/
public static Generator> zip(final Generator generator1, final Generator generator2) {
return new ZipPairGenerator(generator1, generator2);
}
}