package org.simantics.scl.runtime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import org.simantics.scl.runtime.function.Function; import org.simantics.scl.runtime.function.FunctionImpl1; import org.simantics.scl.runtime.function.FunctionImpl2; import org.simantics.scl.runtime.tuple.Tuple2; import gnu.trove.map.hash.TCustomHashMap; import gnu.trove.map.hash.THashMap; import gnu.trove.set.hash.THashSet; import gnu.trove.strategy.HashingStrategy; @SuppressWarnings({"rawtypes", "unchecked"}) public class Lists { public static List map(Function f, List l) { ArrayList result = new ArrayList(l.size()); for(Object a : l) result.add(f.apply(a)); return result; } public static void iter(Function f, List l) { for(Object a : l) f.apply(a); } public static List filter(Function p, List l) { ArrayList result = new ArrayList(Math.min(10, l.size())); for(Object a : l) if((Boolean)p.apply(a)) result.add(a); return result; } public static List filterJust(List l) { ArrayList result = new ArrayList(Math.min(10, l.size())); for(Object a : l) if(a != null) result.add(a); return result; } public static List reverse(List l) { ArrayList result = new ArrayList(l.size()); for(int i=l.size()-1;i>=0;--i) result.add(l.get(i)); return result; } public static Object foldl(Function f, Object initial, List l) { for(Object a : l) initial = f.apply(initial, a); return initial; } // (b -> Maybe (a, b)) -> b -> [a] public static List unfoldr(Function f, Object state) { ArrayList result = new ArrayList(); while(true) { Object r = f.apply(state); if(r == null) return result; Tuple2 t = (Tuple2)r; result.add(t.c0); state = t.c1; } } public static Object foldr(Function f, Object initial, List l) { for(int i=l.size()-1;i>=0;--i) initial = f.apply(initial, l.get(i)); return initial; } public static Object foldl1(Function f, List l) { Iterator it = l.iterator(); Object initial = it.next(); while(it.hasNext()) initial = f.apply(initial, it.next()); return initial; } public static Object foldr1(Function f, List l) { int i=l.size()-1; Object initial = l.get(i); for(--i;i>=0;--i) initial = f.apply(initial, l.get(i)); return initial; } public static List _pp(List a, List b) { ArrayList result = new ArrayList(a.size() + b.size()); result.addAll(a); result.addAll(b); return result; } public static List concat(List l) { int size = 0; for(Object e : l) size += ((List)e).size(); ArrayList result = new ArrayList(size); for(Object e : l) result.addAll((List)e); return result; } public static List append(List a, List b) { ArrayList result = new ArrayList(a.size() + b.size()); result.addAll(a); result.addAll(b); return result; } public static List concatMap(Function f, List l) { return concat(map(f, l)); } public static int length(List l) { return l.size(); } public static boolean forall(Function p, List l) { for(Object e : l) if(!(Boolean)p.apply(e)) return false; return true; } public static boolean exists(Function p, List l) { for(Object e : l) if((Boolean)p.apply(e)) return true; return false; } public static Object get(List l, double i) { return l.get((int)i); } private static final FunctionImpl2 BUILD_FUNC = new FunctionImpl2() { @Override public Object apply(Object p0, Object p1) { ((ArrayList)p0).add(p1); return p0; } }; public static List build(Function f) { return (List)f.apply(new ArrayList(), BUILD_FUNC); } public static List range(int from, int to) { ArrayList result = new ArrayList(); while(from <= to) { result.add(from); ++from; } return result; } public static List newList() { return new ArrayList(2); } public static void add(List a, Object b) { a.add(b); } public static List zip(List a, List b) { int len = Math.min(a.size(), b.size()); ArrayList result = new ArrayList(len); for(int i=0;i l) { final TCustomHashMap map = new TCustomHashMap( new HashingStrategy() { private static final long serialVersionUID = 3130052128660420673L; @Override public int computeHashCode(Object object) { return (Integer)hash.apply(object); } @Override public boolean equals(Object o1, Object o2) { return (Boolean)eq.apply(o1, o2); } }); for(Tuple2 t : l) map.put(t.c0, t.c1); return new FunctionImpl1() { @Override public Object apply(Object p0) { return map.get(p0); } }; } public static Function index(List l) { THashMap map = new THashMap(l.size()); for(Tuple2 t : l) map.put(t.c0, t.c1); return new FunctionImpl1() { @Override public Object apply(Object p0) { return map.get(p0); } }; } public static Function indexSet(List l) { THashSet set = new THashSet(l.size()); for(Object obj : l) set.add(obj); return new FunctionImpl1() { @Override public Object apply(Object p0) { return set.contains(p0); } }; } public static Function indexBy(Function f, List l) { THashMap map = new THashMap(l.size()); for(Object o : l) map.put(f.apply(o), o); return new FunctionImpl1() { @Override public Object apply(Object p0) { return map.get(p0); } }; } // groupWith :: (a -> Integer) -> (a -> a -> Boolean) -> (a -> b) -> [a] -> [(b, [a])] @SuppressWarnings("serial") public static List groupWith(final Function hash, final Function eq, Function keyFunction, Function valueFunction, List input) { final TCustomHashMap> map = new TCustomHashMap>( new HashingStrategy() { @Override public int computeHashCode(Object object) { return (Integer)hash.apply(object); } @Override public boolean equals(Object o1, Object o2) { return (Boolean)eq.apply(o1, o2); } }); ArrayList result = new ArrayList(); for(Object o : input) { Object key = keyFunction.apply(o); ArrayList l = map.get(key); if(l == null) { l = new ArrayList(); map.put(key, l); result.add(new Tuple2(key, l)); } l.add(valueFunction.apply(o)); } return result; } public static List group(List input) { THashMap> groupMap = new THashMap>(); ArrayList result = new ArrayList(); for(Tuple2 t : input) { Object key = t.c0; ArrayList list = groupMap.get(key); if(list == null) { list = new ArrayList(); groupMap.put(key, list); result.add(new Tuple2(key, list)); } list.add(t.c1); } return result; } public static List groupBy(Function f, List input) { THashMap> groupMap = new THashMap>(); ArrayList result = new ArrayList(); for(Object value : input) { Object key = f.apply(value); ArrayList list = groupMap.get(key); if(list == null) { list = new ArrayList(); groupMap.put(key, list); result.add(new Tuple2(key, list)); } list.add(value); } return result; } private static class GroupMapFunction extends FunctionImpl1> { THashMap> groupMap; public GroupMapFunction(THashMap> groupMap) { this.groupMap = groupMap; } @Override public List apply(Object p0) { List result = groupMap.get(p0); if(result == null) return Collections.emptyList(); else return result; } } public static Function indexGroup(List input) { THashMap> groupMap = new THashMap>(); for(Tuple2 t : input) { Object key = t.c0; ArrayList list = groupMap.get(key); if(list == null) { list = new ArrayList(); groupMap.put(key, list); } list.add(t.c1); } return new GroupMapFunction(groupMap); } public static Function indexGroupBy(Function f, List input) { THashMap> groupMap = new THashMap>(); for(Object value : input) { Object key = f.apply(value); ArrayList list = groupMap.get(key); if(list == null) { list = new ArrayList(); groupMap.put(key, list); } list.add(value); } return new GroupMapFunction(groupMap); } public static List sortWith(final Function compare, List l) { Object[] result = l.toArray(new Object[l.size()]); Arrays.sort(result, new Comparator() { @Override public int compare(Object o1, Object o2) { return (Integer)compare.apply(o1, o2); } }); return Arrays.asList(result); } public static List uniqueWith(Function compare, List l) { ArrayList result = new ArrayList(Math.min(10, l.size())); outerLoop: for(int i=0;i unique(List l) { THashSet set = new THashSet(l.size()); ArrayList result = new ArrayList(l.size()); for(Object el : l) if(set.add(el)) result.add(el); return result; } public static List uniqueBy(Function f, List l) { THashSet set = new THashSet(l.size()); ArrayList result = new ArrayList(l.size()); for(Object el : l) if(set.add(f.apply(el))) result.add(el); return result; } }