EN · DE · RU · FR · ES

#354: GeneralAggregation.groovy

projectforge-business/src/main/groovy/GeneralAggregation.groovy Тип: Groovy · Роль: Компонент · Источник: projectforge-business/src/main/groovy/GeneralAggregation.groovy 111 строк · 64 кода · 19 комментариев · 28 пустых
Файл исходного кода в projectforge-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}
	}
	
}

История Git

9ebb88522 Начальный коммит