GeneralAggregation.groovyprojectforge-business/src/main/groovy/GeneralAggregation.groovy, содержащий код Groovy для уровня компонента.Классы: GeneralAggregation
class GeneralAggregation {
public static void main(def args){
// Эквивалентность, если ...
Closure equiv = {l1, l2 -> l1[0] % 5 == l2[0] % 5}
// Среднее арифметическое 4-го и стандартное отклонение 5-го столбца (индексация столбцов начинается с 0)
Closure init = {l -> l[3]=[1,l[3]]
l[4]=[1,l[4]**2]
l}
Closure agg = {l,a -> a[3]=[a[3][0]+=1,a[3][1]+=l[3]]
a[4]=[a[4][0]+=1,a[4][1]+=l[4]**2]}
Closure fin = {a -> a[3] = a[3][1]/a[3][0]
a[4] = (a[4][1]/a[4][0])**0.5}
Closure iaf = {i -> def aggfun = [init,agg,fin]
return [i]}
// Пример данных: обратите внимание, что третья запись должна быть константой для класса эквивалентности
List list = (0..100).collect{n -> [n,2*n,n % 2,n,n]}
aggregate2(list,equiv,init,agg,fin).each{println it}
def lol = (1..10).collect{n -> (1..3).collect{m -> n*m}}
//println lolToLoo(lol,["first","second","third"]).each{o -> println o.first+" "+o.second+" "+o.third}
// Альтернатива с HashMap
List mlist = (0..100).collect{n -> def m = new HashMap()
m['first'] = n
m['second'] = 2*n
m['third'] = n % 2
m['fourth'] = n
m['fifth'] = n
return m}
Closure equiv2 = {l1, l2 -> l1.first % 5 == l2.first % 5}
Closure init2 = {l -> l.fourth=[1,l.fourth]
l.fifth=[1,l.fifth**2]
l}
Closure agg2 = {l,a -> a.fourth=[a.fourth[0]+=1,a.fourth[1]+=l.fourth]
a.fifth=[a.fifth[0]+=1,a.fifth[1]+=l.fifth**2]}
Closure fin2 = {a -> a.fourth = a.fourth[1]/a.fourth[0]
a.fifth = (a.fifth[1]/a.fifth[0])**0.5}
aggregate(mlist,equiv2,init2,agg2,fin2).each{println it}
}
/*
* lol — это список списков, представляющий таблицу (каждый элемент — список, описывающий строку таблицы)
* equiv — отношение эквивалентности на n столбцах списка
* init — замыкание, описывающее инициализацию функции агрегации
* agg — замыкание, описывающее агрегацию функции агрегации
* finalize — замыкание, описывающее финализацию функции агрегации
*/
public static List aggregate2(List<List> lol, Closure equiv, Closure init = {x -> x}, Closure agg, Closure finalize = {x -> x}) {
def resultTable = [] // Таблица с агрегированными значениями
def rep = [] // Строка в resultTable с представителем класса эквивалентности и агрегатом
lol.each{ row ->
if((rep = resultTable.find{r -> equiv(row,r)}) != null) agg(row,rep)
else resultTable << init(row)
}
resultTable.each{finalize(it)}
}
/*
* Замыкание для генерации отношения эквивалентности для агрегации
*/
public static Closure createEquiv(List<String> fields) {
def getter = HashMap.class.getMethod("get",Object)
return {x,y -> fields.inject(true) {cumPropValue, field -> cumPropValue && getter.invoke(x,field) == getter.invoke(y,field)}}
}
/*
* lom — список карт (Map)
*/
public static List aggregate(List<HashMap> lom, Closure equiv, Closure init = {x -> x}, Closure agg, Closure finalize = {x -> x}) {
def resultTable = [] // Таблица с агрегированными значениями
def rep = [] // Строка в resultTable с представителем класса эквивалентности и агрегатом
lom.each{row ->
if((rep = resultTable.find{r -> equiv(row,r)}) != null) agg(row,rep)
else resultTable << init(row)
}
resultTable.each{finalize(it)}
}
// Преобразует объект и список атрибутов (строк) в список значений атрибутов
public static List looToLol(List loo, List attlist) {
Closure o2l = {obj,attList -> attList.collect{att -> obj."${att}"}}
loo.collect{obj -> o2l(obj,attList)}
}
public static List lolToLoo(List lol, List attnames) {
return lol.collect{list -> def x = new Expando()
(0..(attnames.size-1)).each{n -> x."${attnames[n]}" = list[n]}
return x}
}
}
9ebb88522 Начальный коммит