Автор | Сообщение |
|
| постоянный участник
|
Пост N: 1957
Зарегистрирован: 12.09.06
|
|
Отправлено: 09.12.11 05:32. Заголовок: Подскажите алгоритм объединения сумм по одинаковому месяцу ?
Всем привет. Имею двухмерный массив примерно такой: 21,33 25.01.2011 21,33 01.03.2011 21,33 15.04.2011 21,33 28.04.2011 21,33 11.05.2011 19,00 11.05.2011 21,33 11.05.2011 21,33 11.05.2011 19,00 11.05.2011 19,00 11.05.2011 19,00 11.05.2011 19,00 11.05.2011 19,00 11.05.2011 19,00 11.05.2011 19,00 11.05.2011 19,00 11.05.2011 284,31 11.05.2011 21,33 11.05.2011 21,33 01.06.2011 21,33 30.06.2011 21,33 30.06.2011 21,33 04.08.2011 21,33 10.08.2011 21,33 22.09.2011 21,33 22.09.2011 21,33 22.09.2011 Подскажите алгоритм как можно объеденить суммы по одинаковому месяцу. Т.е. чтоб получился массив такого вида: 21,33 25.01.2011 - пропуск т.к. 1-месяц 21,33 01.03.2011 - пропуск т.к. 1-месяц 42,66 15.04.2011 - объединили 0,00 28.04.2011 - .... 540,63 11.05.2011 - объединили 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 0,00 11.05.2011 и т.д. Заранее спасибо за ответ...
| |
|
Ответов - 8
[только новые]
|
|
|
| постоянный участник
|
Пост N: 631
Зарегистрирован: 27.01.07
|
|
Отправлено: 09.12.11 08:13. Заголовок: Как-то так... FUNCT..
Как-то так... FUNCTION Something( aIn ) LOCAL aElem LOCAL nMon := 0 LOCAL n1st LOCAL aOut := {} // результат FOR EACH aElem IN aIn IF nMon <> Month( aElem[ 2 ] ) nMon := Month( aElem[ 2 ] ) AAdd( aOut, aElem ) n1st := Len( aOut ) ELSE aOut[ n1st, 1 ] += aElem[ 1 ] AAdd( aOut, { 0, aElem[ 2 ] } ) END // IF NEXT RETURN aOut
| |
|
|
| |
Пост N: 2227
Зарегистрирован: 17.05.05
|
|
Отправлено: 09.12.11 11:29. Заголовок: Перенес темку сюда...
Перенес темку сюда.
| |
|
|
| постоянный участник
|
Пост N: 1958
Зарегистрирован: 12.09.06
|
|
Отправлено: 09.12.11 13:16. Заголовок: Получилось ! Только ..
Получилось ! Только не совсем правильно, в первом массиве "затирается" (просуммировался) первый элемент месяца. 1 - 25.01.11 , 21.33 -> 21.33 2 - 01.03.11 , 21.33 -> 21.33 3 - 15.04.11 , 42.66 -> 42.66 4 - 28.04.11 , 21.33 -> 0 5 - 11.05.11 , 540.63 -> 540.63 6 - 11.05.11 , 19.00 -> 0 7 - 11.05.11 , 21.33 -> 0 8 - 11.05.11 , 21.33 -> 0 9 - 11.05.11 , 19.00 -> 0 10 - 11.05.11 , 19.00 -> 0 11 - 11.05.11 , 19.00 -> 0 12 - 11.05.11 , 19.00 -> 0 13 - 11.05.11 , 19.00 -> 0 14 - 11.05.11 , 19.00 -> 0 15 - 11.05.11 , 19.00 -> 0 16 - 11.05.11 , 19.00 -> 0 17 - 11.05.11 , 284.31 -> 0 18 - 11.05.11 , 21.33 -> 0 19 - 01.06.11 , 63.99 -> 63.99 20 - 30.06.11 , 21.33 -> 0 21 - 30.06.11 , 21.33 -> 0 22 - 04.08.11 , 42.66 -> 42.66 23 - 10.08.11 , 21.33 -> 0 24 - 22.09.11 , 63.99 -> 63.99 25 - 22.09.11 , 21.33 -> 0 26 - 22.09.11 , 21.33 -> 0 Вот код: Скрытый текст FUNCTION MAIN() LOCAL aDim := {}, nI, aDimOut SET DATE GERMAN SET EPOCH TO 1905 AAdd( aDim, { 21.33 , CTOD("25.01.2011") } ) AAdd( aDim, { 21.33 , CTOD("01.03.2011") } ) AAdd( aDim, { 21.33 , CTOD("15.04.2011") } ) AAdd( aDim, { 21.33 , CTOD("28.04.2011") } ) AAdd( aDim, { 21.33 , CTOD("11.05.2011") } ) AAdd( aDim, { 19.00 , CTOD("11.05.2011") } ) AAdd( aDim, { 21.33 , CTOD("11.05.2011") } ) AAdd( aDim, { 21.33 , CTOD("11.05.2011") } ) AAdd( aDim, { 19.00 , CTOD("11.05.2011") } ) AAdd( aDim, { 19.00 , CTOD("11.05.2011") } ) AAdd( aDim, { 19.00 , CTOD("11.05.2011") } ) AAdd( aDim, { 19.00 , CTOD("11.05.2011") } ) AAdd( aDim, { 19.00 , CTOD("11.05.2011") } ) AAdd( aDim, { 19.00 , CTOD("11.05.2011") } ) AAdd( aDim, { 19.00 , CTOD("11.05.2011") } ) AAdd( aDim, { 19.00 , CTOD("11.05.2011") } ) AAdd( aDim, {284.31 , CTOD("11.05.2011") } ) AAdd( aDim, { 21.33 , CTOD("11.05.2011") } ) AAdd( aDim, { 21.33 , CTOD("01.06.2011") } ) AAdd( aDim, { 21.33 , CTOD("30.06.2011") } ) AAdd( aDim, { 21.33 , CTOD("30.06.2011") } ) AAdd( aDim, { 21.33 , CTOD("04.08.2011") } ) AAdd( aDim, { 21.33 , CTOD("10.08.2011") } ) AAdd( aDim, { 21.33 , CTOD("22.09.2011") } ) AAdd( aDim, { 21.33 , CTOD("22.09.2011") } ) AAdd( aDim, { 21.33 , CTOD("22.09.2011") } ) aDimOut := Something( aDim ) FOR nI := 1 TO Len( aDim ) ? nI, " - ", DTOC(aDim[ nI,2 ]), ", ", aDim[ nI,1 ] , " -> ", aDimOut[ nI,1 ] NEXT wait RETURN NIL //////////////////////////////////////////////////////////// FUNCTION Something( aIn ) LOCAL aElem LOCAL nMon := 0 LOCAL n1st LOCAL aOut := {} // результат FOR EACH aElem IN aIn IF nMon <> Month( aElem[ 2 ] ) nMon := Month( aElem[ 2 ] ) AAdd( aOut, aElem ) n1st := Len( aOut ) ELSE aOut[ n1st, 1 ] += aElem[ 1 ] AAdd( aOut, { 0, aElem[ 2 ] } ) END // IF NEXT RETURN aOut
|
| |
|
|
| постоянный участник
|
Пост N: 632
Зарегистрирован: 27.01.07
|
|
Отправлено: 09.12.11 14:29. Заголовок: Andrey пишет: в пер..
Andrey пишет: цитата: | в первом массиве "затирается" (просуммировался) первый элемент месяца |
| Замени строку AAdd( aOut, aElem ) на AAdd( aOut, AClone( aElem ) )
| |
|
|
| постоянный участник
|
Пост N: 1960
Зарегистрирован: 12.09.06
|
|
Отправлено: 09.12.11 14:43. Заголовок: Спасибо БОЛЬШОЕ PSP ..
Спасибо БОЛЬШОЕ PSP !!! А то после недельной работы по ночам голова совсем "не варит"...
| |
|
|
| Администратор
|
Пост N: 2201
Зарегистрирован: 23.05.05
|
|
Отправлено: 09.12.11 19:10. Заголовок: Маленький совет. Нас..
Маленький совет. Насколько я понимаю, исходный массив получен в результате выборки из БД. Результирующий массив можно получить непосредственно, не формируя промежуточный. Примерно так: aRes := {} seek ... while ... AADDQ(aRes, Date, Summa) skip enddo ... func AADDQ(aRes, xKey, nSum) ... retu nil
| |
|
|
| Администратор
|
Пост N: 2207
Зарегистрирован: 23.05.05
|
|
Отправлено: 17.12.11 12:37. Заголовок: Перенес функцию, фор..
Перенес функцию, формирующую результирующий массив, на C-уровень http://zalil.ru/32298640 Пример использования: Local aRes := {} dbEval({|| AADDU(aRes, Date, Summa)}) 2-й параметр - ключ для поиска в массиве, 3-й и так далее - числовые параметры для суммирования Синтаксис вызова функции: AADDU(<aArray>, <xKey>, <nSum1>, [nSum2], ...) Функция выполняет поиск ключа в массиве методом половинного деления, и работает очень быстро. Результирующий массив получается вида: {{xKey1, nSum1, ...}, {xKey2, nSum2, ...}, ...} Результирующий массив сразу отсортирован В модуле также имеется функция AADDS() с аналогичными параметрами. Ее отличие от AADDU в том, что входной поток для нее предполагается отсортированным, и ключ сравнивается только с последним элементом массива. Но, поскольку метод половинного деления у меня реализован не классическим способом, а несколько модифицированным: сначала сравнение выполняется на границы массива, первый и последний элемент, разница в производительности между AADDU и AADDS незначительна. Вместо поиска в массиве методом половинного деления, конечно, можно с тем же результатом использовать тип данных хэш. Но я уже привык к своему способу, да и, как я уже написал, поиск у меня немного отличается. Тесты показывают, что перенос этого кода на C-уровень дает увеличение производительности примерно в полтора раза. Это при том, что источник данных один и то же. Я сравнивал с функцией, которая в качестве параметра получает подмассив: AADDQ(aRes, {xKey, nSum}) Ну а в сравнении с алгоритмом, используюшим обычный линейный поиск, производительность возрастает раза в 3. В этом модуле есть еще несколько функций работы с массивами, но они уже предназначены для других целей.
| |
|
|
| постоянный участник
|
Пост N: 1975
Зарегистрирован: 12.09.06
|
|
Отправлено: 17.12.11 13:26. Заголовок: Pasha пишет: Тесты ..
Pasha пишет: цитата: | Тесты показывают, что перенос этого кода на C-уровень дает увеличение производительности примерно в полтора раза. Это при том, что источник данных один и то же. Я сравнивал с функцией, которая в качестве параметра получает подмассив: AADDQ(aRes, {xKey, nSum}) Ну а в сравнении с алгоритмом, используюшим обычный линейный поиск, производительность возрастает раза в 3. |
| Ну что сказать - видно руку профессионала ! Спасибо БОЛЬШОЕ !!!
| |
|
|
|