com.arosbio.commons.CollectionUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of confai Show documentation
Show all versions of confai Show documentation
Conformal AI package, including all data IO, transformations, machine learning models and predictor classes. Without inclusion of chemistry-dependent code.
/*
* Copyright (C) Aros Bio AB.
*
* CPSign is an Open Source Software that is dual licensed to allow you to choose a license that best suits your requirements:
*
* 1) GPLv3 (GNU General Public License Version 3) with Additional Terms, including an attribution clause as well as a limitation to use the software for commercial purposes.
*
* 2) CPSign Proprietary License that allows you to use CPSign for commercial activities, such as in a revenue-generating operation or environment, or integrate CPSign in your proprietary software without worrying about disclosing the source code of your proprietary software, which is required if you choose to use the software under GPLv3 license. See arosbio.com/cpsign/commercial-license for details.
*/
package com.arosbio.commons;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import com.google.common.collect.Range;
public class CollectionUtils {
/**
* IndexedValues are sorted descending depending on their value.
* Used e.g. by the FeatureSelectors for keeping the indices with most variance/importance
* @author staffan
*
*/
public static class IndexedValue implements Cloneable, Comparable {
public final int index;
public final double value;
public IndexedValue(int index, double value) {
this.index = index;
this.value = value;
}
public IndexedValue withValue(double newValue){
return new IndexedValue(index, newValue);
}
@Override
public int compareTo(IndexedValue o) {
int cmp = Double.compare(this.value, o.value);
return cmp != 0 ? cmp : this.index - o.index ;
}
public String toString() {
return String.format("%d:%s",index,value);
}
public IndexedValue clone() {
return new IndexedValue(index, value);
}
}
public static int countTrueValues(Collection values) {
int sum = 0;
for (boolean b : values) {
if (b)
sum++;
}
return sum;
}
/**
* Uses the {@link #listRange(double, double, double)} using default {@code step} of 1
* @param start the start value
* @param end the end value
* @return a List of values between start and end
*/
public static List listRange(double start, double end){
return listRange(start,end, 1d);
}
public static List listRange(double start, double end, double step){
// Special treat if start and end equals
if (Math.abs(start-end)<0.00000001){
return Arrays.asList(start);
}
// validate input
if (Math.abs(step) <= 0.0001){
throw new IllegalArgumentException("step parameter cannot be 0");
}
if (start > end && step >= 0){
throw new IllegalArgumentException(String.format("Invalid range enumeration {start=%s,end=%s,step=%s}", start,end,step));
} else if (start < end && step <= 0){
throw new IllegalArgumentException(String.format("Invalid range enumeration {start=%s,end=%s,step=%s}", start,end,step));
}
if (start < end){
if ( (end-start) / step > 1000 ) {
throw new IllegalArgumentException("Not allowed to create a list range with more than 1000 entries");
}
List result = new ArrayList<>((int) ((end-start)/step));
int i=0;
double nextValue = start;
while (i < 1001 && (nextValue < end || MathUtils.equals(nextValue, end))) {
result.add(nextValue);
i++;
nextValue = start + i*step;
}
return result;
} else {
// start > end (equals treated before)
if ( (start-end) / step > 1000 ) {
throw new IllegalArgumentException("Not allowed to create a list range with more than 1000 entries");
}
List result = new ArrayList<>((int) ((end-start)/step));
int i=0;
double nextValue = start;
while (i < 1001 && (nextValue > end || MathUtils.equals(nextValue, end))) {
result.add(nextValue);
i++;
nextValue = start + i*step;
}
return result;
}
}
public static List listRange(double start, double stop, double step, double base){
return listRange(start,stop,step)
.stream()
.map(e -> Math.pow(base, e))
.collect(Collectors.toList());
}
public static List listRange(int start, int end){
return listRange(start, end, 1);
}
public static List listRange(int start, int end, int step){
// Special treat if start and end equals
if (start==end){
return Arrays.asList(start);
}
// validate input
if (Math.abs(step) <= 0.0001){
throw new IllegalArgumentException("step parameter cannot be 0");
}
if (start > end && step >= 0){
throw new IllegalArgumentException(String.format("Invalid range enumeration {start=%s,end=%s,step=%s}", start,end,step));
} else if (start < end && step <= 0){
throw new IllegalArgumentException(String.format("Invalid range enumeration {start=%s,end=%s,step=%s}", start,end,step));
}
if (start < end){
if ( (double)(end-start) / step > 1000 ) {
throw new IllegalArgumentException("Not allowed to create a list range with more than 1000 entries");
}
List result = new ArrayList<>((int) ((end-start)/step));
for (int i=start; i<=end; i+= step) {
result.add(i);
}
return result;
} else {
// start > end
if ( (double)(start-end) / step > 1000 ) {
throw new IllegalArgumentException("Not allowed to create a list range with more than 1000 entries");
}
List result = new ArrayList<>((int) ((end-start)/step));
for (int i=start; i>=end; i+= step) {
result.add(i);
}
return result;
}
}
public static Pair,List> splitRandomly(List input, int numInSecond, long seed){
List first = new ArrayList<>(input), // Shallow copy all to the first
second = new ArrayList<>(numInSecond);
Random rng = new Random(seed);
for (int i=0; i input) {
for (Double n : input) {
if (n == null || n.isNaN()) {
return true;
}
}
return false;
}
public static boolean containsNull(Collection input) {
for (T t : input) {
if (t == null)
return true;
}
return false;
}
public static List filterNullOrNaN(Collection input) {
List res = new ArrayList<>();
for (Double n : input) {
if (n != null && Double.isFinite(n))
res.add(n);
}
return res;
}
public static double[] toArray(List input) {
if (input == null || input.isEmpty())
return new double[0];
double[] arr = new double[input.size()];
for (int i=0; i input) {
if (input == null || input.isEmpty())
return new int[0];
int[] arr = new int[input.size()];
for (int i=0; i Map countFrequencies(Collection input){
Map freqs = new HashMap<>();
for (T t : input) {
freqs.put(t, freqs.getOrDefault(t, 0)+1);
}
return freqs;
}
public static int countValuesSmallerThan(Collection vals, int threshold) {
int count=0;
for (int v : vals) {
if (v < threshold)
count++;
}
return count;
}
public static > List getUnique(Collection input){
Set asSet = new LinkedHashSet<>(input); // Keep ordering using linked hash set
List asList = new ArrayList<>(asSet);
return asList;
}
public static > List getUniqueAndSorted(Collection input){
return input.stream()
.distinct()
.sorted()
.collect(Collectors.toCollection(ArrayList::new));
}
public static >
boolean isSorted(Iterable iterable) {
Iterator iter = iterable.iterator();
if (!iter.hasNext()) {
return true;
}
T t = iter.next();
while (iter.hasNext()) {
T t2 = iter.next();
if (t.compareTo(t2) > 0) {
return false;
}
t = t2;
}
return true;
}
public static > List sort(Collection c){
List list = new ArrayList<>(c);
Collections.sort(list);
return list;
}
public static List