/** * weak == true :there is a next element iff heads contains * at least of element not null * weak == false: there is a next element iff all elements of head * are not null * * @return true iff there is a next element */ public boolean hasNext() { return weak ? any(heads, x -> x != null) : all(heads, x -> x != null); }
/** * an iterator yielding the Fibonacci series * * @return the fibonacci series as InfiniteIterator */ static InfiniteIterator<Integer> fibonacci() { return binaryGenerator(1, 1, (a, b) -> a + b); }
/** * @param <T> any type * @param zippedIterator iterator of lists; must not be empty. * The lists are typically but not necessarily * of equal size. * @return list of iterators to be iterated on independently * The result's size is that of the first list; subsequent lists * are truncated if longer and padded with nulls if shorter */ public static <T> List<ImmutableIterator<T>> unzip(Iterator<List<T>> zippedIterator) { List<T> firstColumn = zippedIterator.next(); int n = firstColumn.size(); @SuppressWarnings("unchecked") List<ImmutableIterator<List<T>>> aux = tee(concat(of(firstColumn), zippedIterator), n); List<ImmutableIterator<T>> result = new ArrayList<>(n); for (int i = 0; i < n; i++) { int j = i; // j is effectively final, i is not result.add(j, map(aux.get(j), xs -> j < xs.size() ? xs.get(j) : null)); } return result; }
/** * @param ts a time series * @param <T> the time type * @param <V> the value type * @param op an operator reducing the value list * @return a new time series unioning all time stamps given, * the value being the result of the reducing by op (e.g. min, max, avg) */ public static <T extends Comparable<T>, V> TimeSeries<T, V> merge(Iterable<TimeSeries<T, V>> ts, BinaryOperator<V> op) { BinaryOperator<V> wop = weakBinaryOperator(op); Iterator<Pair<T, List<V>>> aux1 = new TimeSeriesMerge<>(map(asIterator(ts), Iterable::iterator)); Iterator<Pair<T, V>> aux2 = map(aux1, (Pair<T, List<V>> p) -> pairOf(p.getFirst(), reduce(asIterator(p.getSecond()), wop))); return new TimeSeries<>(aux2); }
/** * @param ts a time series * @param <T> the time type * @param <V> the value type * @return a new time series unioning all time stamps given, * the value being the list of all values valid at that time */ public static <T extends Comparable<T>, V> TimeSeries<T, List<V>> merge(Iterable<TimeSeries<T, V>> ts) { Iterator<Pair<T, List<V>>> aux = new TimeSeriesMerge<>(map(asIterator(ts), Iterable::iterator)); return new TimeSeries<>(aux); }
/** * @param p the predicate to be applied * @return true if at least one element of this satisfies p */ public boolean any(Predicate<? super T> p) { return Iterators.any(this, p); }
/** * @param xs the iterable to be tested * @param p the predicate to be applied * @param <T> any type * @return all elements of xs which satisfy p */ public static <T> ImmutableIterator filter(Iterable<T> xs, Predicate<? super T> p) { return filter(xs.iterator(), p); }
/** * @param p the predicate to be applied * @return true if all elements of this satisfy p */ public boolean all(Predicate<? super T> p) { return Iterators.all(this, p); }
/** * @param <T> any type * @param ts iterators to be concatenated * @return the concatenation of all t in ts */ public static <T> ImmutableIterator<T> concat(Iterator<T>... ts) { if (ts.length < 1) { return empty(); } return new ImmutableIterator<T>() { private int cnt = 0; @Override public boolean hasNext() { return (cnt < ts.length && ts[cnt].hasNext()) || (++cnt < ts.length && ts[cnt].hasNext()); } @Override public T next() { if (hasNext()) { return ts[cnt].next(); } else { throw new NoSuchElementException(); } } }; }
/** * @param ts an iterator of iterators * @return the concatenation of this and all iterators of ts */ @SuppressWarnings("unchecked") public FluentIterator<T> concat(Iterator... ts) { Iterator<T>[] tmp = Arrays.copyOf(ts, ts.length + 1); tmp[0] = this; System.arraycopy(ts, 0, tmp, 1, ts.length); return fluent(Iterators.concat(tmp)); }
/** * @param n the number of elements to be considered * @return an iterator containing at most n elements */ public FluentIterator<T> limit(int n) { return fluent(Iterators.limit(this, n)); }
/** * This function groups an iterator by a key function: * consecutive elements with the same key value form a group. * The result is an Iterator of Lists of objects * Example: 4 7 10 5 8 11 3, key(x) = x%3 produces ((4 7 10) (5 8 11) (3)) * * @param key the key function controlling the grouping * @param <K> any type * @return the grouped iterator */ public <K> FluentIterator<List<T>> groupBy(Function<T, K> key) { return fluent(Iterators.groupBy(this, key)); }
/** * This method merges n time series into one according to the following strategy: * The timestamps are merged; the resulting sequence is the union of the given ones. * On each timestamp, the new value is computed by reducing the given operator to * the vector of values at that time stamp. * Typical operators are min, max, sum, avg. * * @param input an iterable of time series to be merged * @param op the operator to be applied * @param <T> type of timestamps * @param <V> type of values * @return iterator of merged timeValuePairs */ public static <T extends Comparable<T>, V> Iterator<Pair<T, V>> merge(Iterable<Iterator<Pair<T, V>>> input, BinaryOperator<V> op) { return map(merge(input), (Pair<T, List<V>> p) -> pairOf(p.getFirst(), reduce(asIterator(p.getSecond()), weakBinaryOperator(op)))); }
/** * @param tv the first time series * @param tw the second time series * @param f a function mapping V x V -> U (e.g. x, y -> x <= y) * @param <T> type of timestamps * @param <V> type of values * @param <U> return type of f * @return a new time series unioning all time stamps given, * the value being the result of f (e.g. lessThan, equals) */ public static <T extends Comparable<T>, V, U> TimeSeries<T, U> merge(TimeSeries<T, V> tv, TimeSeries<T, V> tw, BiFunction<V, V, U> f) { Iterator<Pair<T, List<V>>> aux1 = asIterator(merge(asList(tv, tw))); Iterator<Pair<T, U>> aux2 = map(aux1, (Pair<T, List<V>> p) -> pairOf(p.getFirst(), f.apply(p.getSecond().get(0), p.getSecond().get(1)))); return new TimeSeries<>(aux2); }
@Override public boolean hasNext() { return any(heads, x -> x != null); }
/** * @param p the predicate to be applied * @return an iterator containing all elements satisfying p */ @SuppressWarnings("unchecked") public FluentIterator<T> filter(Predicate<? super T> p) { return fluent(Iterators.filter(this, p)); }
/** * @param xs the iterable to be tested * @param p the predicate to be applied * @param <T> any type * @return true iff all x in xs satisfy p */ public static <T> boolean all(Iterable<T> xs, Predicate<? super T> p) { return all(xs.iterator(), p); }