Bläddra i källkod

new: CQuery#filterEach
new: MathStats

Mariusz Czarnowski 4 år sedan
förälder
incheckning
b75ee34fac

+ 27 - 7
assira.core/src/main/java/net/ranides/assira/collection/iterators/IteratorUtils.java

@@ -12,6 +12,7 @@ import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
 import net.ranides.assira.functional.Functions.EachFunction;
+import net.ranides.assira.functional.Predicates.EachPredicate;
 import net.ranides.assira.functional.checked.CheckedSupplier;
 import net.ranides.assira.generic.CompareUtils;
 
@@ -98,6 +99,14 @@ public final class IteratorUtils {
 	public static <T> ListIterator<T> filter(ListIterator<? extends T> iterator, Predicate<? super T> predicate) {
         return new FilterListIterator<>(iterator, predicate, false);
     }
+
+    public static <T> Iterator<T> filterEach(Iterator<? extends T> iterator, EachPredicate<? super T> predicate) {
+        return new FilterIterator<>(iterator, predicate, false);
+    }
+
+    public static <T> ListIterator<T> filterEach(ListIterator<? extends T> iterator, EachPredicate<? super T> predicate) {
+        return new FilterListIterator<>(iterator, predicate, false);
+    }
     
     public static <T> Iterator<T> limit(Iterator<? extends T> iterator, Predicate<? super T> predicate) {
         return new FilterIterator<>(iterator, predicate, true);
@@ -414,15 +423,21 @@ public final class IteratorUtils {
     private static class FilterIterator<T> implements Iterator<T> {
 
         private final Iterator<? extends T> iterator;
-        private final Predicate<? super T> predicate;
+        private final EachPredicate<? super T> predicate;
         private final boolean limit;
         private T next;
         private boolean hasNext;
-        
+        private int index;
+
         public FilterIterator(Iterator<? extends T> iterator, Predicate<? super T> predicate, boolean limit) {
+            this(iterator, (i,v) -> predicate.test(v), limit);
+        }
+
+        public FilterIterator(Iterator<? extends T> iterator, EachPredicate<? super T> predicate, boolean limit) {
             this.iterator = iterator;
 			this.predicate = predicate;
             this.limit = limit;
+            this.index = -1;
             nextMatch();
         }
 
@@ -436,6 +451,7 @@ public final class IteratorUtils {
             if (!hasNext) {
                 throw new NoSuchElementException();
             }
+            index++;
             return nextMatch();
         }
 
@@ -444,7 +460,7 @@ public final class IteratorUtils {
 
             while (iterator.hasNext()) {
                 T value = iterator.next();
-                if (predicate.test(value)) {
+                if (predicate.test(index, value)) {
                     hasNext = true;
                     next = value;
                     return last;
@@ -468,13 +484,17 @@ public final class IteratorUtils {
 	private static class FilterListIterator<T> implements ListIterator<T> {
 
         private final ListIterator<? extends T> iterator;
-        private final Predicate<? super T> predicate;
+        private final EachPredicate<? super T> predicate;
         private final boolean limit;
-		int index;
+        private int index;
 		private T next;
         private boolean hasNext;
 
         public FilterListIterator(ListIterator<? extends T> iterator, Predicate<? super T> predicate, boolean limit) {
+            this(iterator, (i,v) -> predicate.test(v), limit);
+        }
+
+        public FilterListIterator(ListIterator<? extends T> iterator, EachPredicate<? super T> predicate, boolean limit) {
             this.iterator = iterator;
 			this.predicate = predicate;
             this.limit = limit;
@@ -514,7 +534,7 @@ public final class IteratorUtils {
 			
             while (iterator.hasNext()) {
                 T value = iterator.next();
-                if (predicate.test(value)) {
+                if (predicate.test(index, value)) {
                     hasNext = true;
                     next = value;
                     return ilast;
@@ -530,7 +550,7 @@ public final class IteratorUtils {
 		private T prevMatch() {
             while (iterator.hasPrevious()) {
                 T value = iterator.previous();
-                if (predicate.test(value)) {
+                if (predicate.test(index, value)) {
                     hasNext = true;
                     next = value;
                     return next;

+ 2 - 0
assira.core/src/main/java/net/ranides/assira/collection/query/CQuery.java

@@ -87,6 +87,8 @@ public interface CQuery<T> extends Iterable<T> {
 
     CQuery<T> filter(Predicate<? super T> p);
 
+    CQuery<T> filterEach(EachPredicate<? super T> p);
+
     <R> CQuery<R> filter(Class<R> p);
 
     <R> CQuery<R> filter(IClass<R> p);

+ 5 - 0
assira.core/src/main/java/net/ranides/assira/collection/query/CQueryAbstract.java

@@ -126,6 +126,11 @@ public abstract class CQueryAbstract<T> implements CQuery<T> {
         return new CQIterable<>(() -> IteratorUtils.filter(iterator(), p));
     }
 
+    @Override
+    public CQuery<T> filterEach(EachPredicate<? super T> p) {
+        return new CQIterable<>(() -> IteratorUtils.filterEach(iterator(), p));
+    }
+
     @Override
     public <R> CQuery<R> filter(Class<R> p) {
         return filter(p::isInstance).map(p::cast);

+ 102 - 0
assira.core/src/main/java/net/ranides/assira/math/MathStats.java

@@ -0,0 +1,102 @@
+package net.ranides.assira.math;
+
+import lombok.Data;
+import net.ranides.assira.collection.lookups.HashLookup;
+import net.ranides.assira.collection.lookups.Lookup;
+import net.ranides.assira.collection.query.CQuery;
+import net.ranides.assira.generic.CompareUtils;
+
+import java.util.DoubleSummaryStatistics;
+import java.util.List;
+
+public class MathStats {
+
+    public static <T> Mode<T> mode(CQuery<T> data) {
+        return new Mode<>(data);
+    }
+
+    public static StandardDeviation deviation(CQuery<? extends Number> data) {
+        return new StandardDeviation(data);
+    }
+
+    @Data
+    public static class Mode<T> {
+
+        private final T value;
+        private final int count;
+        private final int domain;
+
+        private Mode(CQuery<T> data) {
+            List<T> list = data.list();
+
+            this.domain = list.size();
+
+            if(list.get(0) instanceof Comparable<?>) {
+                list.sort(CompareUtils.comparator());
+                T lastV = null;
+                T currV = null;
+                int lastC = 0;
+                int currC = 0;
+
+                for(T v : list) {
+                    if(v == currV) {
+                        currC++;
+                    } else {
+                        if(currC > lastC) {
+                            lastV = currV;
+                            lastC = currC;
+                        }
+                        currC = 1;
+                        currV = v;
+                    }
+                }
+                if(currC > lastC) {
+                    lastV = currV;
+                    lastC = currC;
+                }
+                this.value = lastV;
+                this.count = lastC;
+
+            } else {
+                Lookup<T> lookup = new HashLookup<>();
+                T lastV = null;
+                int lastC = 0;
+                for(T v : list) {
+                    int c = lookup.inc(v);
+                    if(c > lastC) {
+                        lastC = c;
+                        lastV = v;
+                    }
+                }
+                this.value = lastV;
+                this.count = lastC;
+            }
+
+        }
+    }
+
+    @Data
+    public static class StandardDeviation {
+
+        private final double average;
+        private final double variance;
+        private final double deviation;
+
+        private StandardDeviation(CQuery<? extends Number> data) {
+            DoubleSummaryStatistics statAvg = data.stream()
+                    .mapToDouble(Number::doubleValue)
+                    .summaryStatistics();
+
+            double avg2 = MathUtils.square(statAvg.getAverage());
+
+            DoubleSummaryStatistics statVar = data.stream()
+                    .mapToDouble(Number::doubleValue)
+                    .map(x -> MathUtils.square(avg2 - x * x))
+                    .summaryStatistics();
+
+            this.average = statAvg.getAverage();
+            this.variance = statVar.getAverage();
+            this.deviation = Math.sqrt(statVar.getAverage());
+        }
+    }
+}

+ 4 - 0
assira.core/src/main/java/net/ranides/assira/math/MathUtils.java

@@ -166,6 +166,10 @@ public final class MathUtils {
         x |= x >> 16;
         return (x | x >> 32) + 1;
     }
+
+    public static double square(double a) {
+        return a * a;
+    }
     
     public static int gcd(int a, int b) { 
         return b==0 ? a : gcd(b, a % b); 

+ 16 - 0
assira.core/src/test/java/net/ranides/assira/math/MathStatsTest.java

@@ -0,0 +1,16 @@
+package net.ranides.assira.math;
+
+import net.ranides.assira.collection.query.CQuery;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class MathStatsTest {
+
+    @Test
+    public void mode() {
+        CQuery<Integer> v1 = CQuery.from().values(1, 2, 5, 5, 3, 2, 7, 2, 1, 2, 1, 5, 9);
+        assertEquals((Integer) 2, MathStats.mode(v1).getValue());
+        assertEquals(4, MathStats.mode(v1).getCount());
+    }
+}