30.10.2015, 12:45 | #1 |
Участник
|
Поиск медианы
Добрый день.
Спешу поделиться алгоритмом поиска медины. Немного теории: Медиан - возможное значение признака, которое делит ранжированную совокупность (вариационный ряд выборки) на две равные части: 50 % «нижних» единиц ряда данных будут иметь значение признака не больше, чем медиана, а «верхние» 50 % — значения признака не меньше, чем медиана. Немного практики: Логика выполнения: - Отсортировать массив; - Если кол-во чисел четное, то найти среднее между серединными ячейками массива; - Если кол-во числе не четное, то взять серединную ячейку. X++: static real con2median(container _con) { container con; int lenCon = conLen(_con), i; real ret; anytype any; ; for(i = 1; i <= lenCon; i++) { any = conPeek(_con, i); con += any2real(any); } con = quickSort(con); info(con2Str_NV(con, '\n')); if(lenCon mod 2 == 0) { ret = conPeek(con, trunc(lenCon / 2)); ret += conPeek(con, trunc(lenCon / 2) + 1); ret = ret / 2; } else { ret = conPeek(con, trunc(lenCon / 2)); } return ret; } Я использую контейнер, т.к. при поиске медианы важны все данные. Set и Map убирает дубликаты. Друзья, если есть идеи по улучшению алгоритмы, то говорите. Буду рад узнать что-то новое. |
|
|
За это сообщение автора поблагодарили: AP-1055D (1). |
30.10.2015, 14:43 | #2 |
Гость
|
|
|
|
За это сообщение автора поблагодарили: demianimp (1). |
30.10.2015, 14:58 | #3 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: S.Kuskov (2), demianimp (1). |
30.10.2015, 18:24 | #4 |
Участник
|
ArrayList == System.Collections.ArrayList?
У меня при ArrayList.add() с разными типами. Метод ArrayList.sort() в ошибку падает. Цитата:
У меня нет метода insert в Set, только add. |
|
30.10.2015, 18:27 | #5 |
Участник
|
X++: static real con2median(container _con) { container con; int lenCon = conLen(_con), i; real ret; anytype any; ; for(i = 1; i <= lenCon; i++) { any = conPeek(_con, i); con += any2real(any); } con = quickSort(con); if(lenCon mod 2 == 0) { ret = conPeek(con, trunc(lenCon / 2)); ret += conPeek(con, trunc(lenCon / 2) + 1); ret = ret / 2; } else { ret = conPeek(con, trunc(lenCon / 2) + 1); } return ret; } { ret = conPeek(con, trunc(lenCon / 2) + 1); } ... Нашел у себя ошибку и мусор небольшой. Исправил. |
|
30.10.2015, 19:14 | #6 |
Участник
|
Цитата:
На всякий случай напомню, что индексировать можно и временные таблицы (в любых версиях Axapta) Ну, и идея, которую подкинул (но не развернул) belugin. Если у Вас есть повторяющиеся значения, то для уникальности надо "подмешать" дополнительное значение. Вариантов "вагон и маленькая тележка" Ну, например так X++: Set set; SetEnumerator se; ; set = new Set(types::Container); set.add([5, set.elements() + 1]); set.add([1, set.elements() + 1]); set.add([2, set.elements() + 1]); set.add([1, set.elements() + 1]); set.add([1, set.elements() + 1]); set.add([3, set.elements() + 1]); info(strFmt('Элементов %1', set.elements())); se = set.getEnumerator(); while (se.moveNext()) { info(strFmt('Значение = %1, Номер вставки = %2', conPeek(se.current(),1), conPeek(se.current(),2))); } return; Но если вместо Set использовать индексированную таблицу будет еще проще
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... Последний раз редактировалось Владимир Максимов; 30.10.2015 в 19:20. |
|
|
За это сообщение автора поблагодарили: demianimp (1). |
30.10.2015, 19:45 | #7 |
Участник
|
Цитата:
Владимир Максимов , большое спасибо за разнесения. Теперь включу нуба А как из табличной переменой или set выдернуть медиану? Перебирать через цикл и останавливаться на нужной записи? |
|
31.10.2015, 06:07 | #8 |
NavAx
|
Как в обычном sql. Через count находишь количество записей, а потом while-ом отматываешь до нужной. По сравнению с quickSort должно быть гораздо быстрее искаться. Главное данные изначально в индексированную таблицу пихать, минуя стадию container-а.
__________________
Isn't it nice when things just work? |
|
|
За это сообщение автора поблагодарили: mazzy (2), demianimp (1). |
31.10.2015, 21:20 | #9 |
Участник
|
Цитата:
Попробуйте, поделитесь результатами исследования. |
|
|
За это сообщение автора поблагодарили: demianimp (1). |
02.11.2015, 09:12 | #10 |
Гость
|
Цитата:
А почему у вас ArrayList.add() с разными типами? Если смотреть ваше преобразование то any2real как бы сводит все к одному типу. Сортировка на real у меня выполняется без ошибок. Подозреваю что в силу кучи причин это будет быстрее + корректнее чем самописки сортировки. |
|
02.11.2015, 13:05 | #11 |
Участник
|
Цитата:
|
|
02.11.2015, 13:27 | #12 |
Участник
|
Вот новый код алгоритм поиска с System.Collections.ArrayList:
X++: static real con2median(container _con) { System.Collections.ArrayList arrayList = new System.Collections.ArrayList(); container con; int lenCon = conLen(_con), i; real ret, ret1; anytype any; ; for(i = 1; i <= lenCon; i++) { arrayList.Add(any2real(conPeek(_con, i))); } arrayList.Sort(); if(lenCon mod 2 == 0) { ret = arrayList.get_Item(real2int(trunc(lenCon / 2)) - 1); ret1 = arrayList.get_Item(real2int(trunc(lenCon / 2))); ret = (ret + ret1) / 2; } else { ret = arrayList.get_Item(real2int(trunc(lenCon / 2))); } return ret; } |
|
|
За это сообщение автора поблагодарили: Pandasama (1). |
02.11.2015, 13:50 | #13 |
Гость
|
Как подозреваю фактически без дополнительных усилий он будет сравнивать любые подобные данные (строки к примеру или числа)
|
|
02.11.2015, 17:02 | #14 |
Участник
|
Он работает с любым простым типом NET. В принципе, даже с разными типами должен работать, если они совместимы между собой. Из C# можно заставить его работать с любым типом, реализовав свой ICompare. Из DAX, понятно, ICompare не реализуешь, поэтому придется обойтись стандартными.
|
|
Теги |
axapta, медиана, ax2009 |
|
Похожие темы | ||||
Тема | Ответов | |||
Как сделать в lookup поиск по нескольким полям | 6 | |||
Поиск набором в выпадающем списке.. | 0 | |||
"поиск" | 6 | |||
Поиск по подстроке | 8 | |||
Поиск по полю временной таблицы | 2 |
|