AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 30.10.2015, 12:45   #1  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Поиск медианы
Добрый день.

Спешу поделиться алгоритмом поиска медины.

Немного теории:
Медиан - возможное значение признака, которое делит ранжированную совокупность (вариационный ряд выборки) на две равные части: 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;
}
Код метода quickSort взят от сюда --> Сортировка контейнеров


Я использую контейнер, т.к. при поиске медианы важны все данные. Set и Map убирает дубликаты.

Друзья, если есть идеи по улучшению алгоритмы, то говорите. Буду рад узнать что-то новое.
За это сообщение автора поблагодарили: AP-1055D (1).
Старый 30.10.2015, 14:43   #2  
axm2013
Гость
 
n/a
Цитата:
Сообщение от demianimp Посмотреть сообщение
...

Я использую контейнер, т.к. при поиске медианы важны все данные. Set и Map убирает дубликаты.
А почему не использовать ArrayList ?
За это сообщение автора поблагодарили: demianimp (1).
Старый 30.10.2015, 14:58   #3  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от demianimp Посмотреть сообщение
Я использую контейнер, т.к. при поиске медианы важны все данные. Set и Map убирает дубликаты.
Если подмешать к данным счетчик, то дубликатов не будет.

X++:
container dataKey = xxxxxx;
index ++;
mySet.insert(dataKey + [index])
За это сообщение автора поблагодарили: S.Kuskov (2), demianimp (1).
Старый 30.10.2015, 18:24   #4  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Цитата:
Сообщение от axm2013 Посмотреть сообщение
А почему не использовать ArrayList ?
ArrayList == System.Collections.ArrayList?

У меня при ArrayList.add() с разными типами. Метод ArrayList.sort() в ошибку падает.

Цитата:
Сообщение от belugin Посмотреть сообщение
Если подмешать к данным счетчик, то дубликатов не будет.

X++:
container dataKey = xxxxxx;
index ++;
mySet.insert(dataKey + [index])
belugin, Не понял с mySet.insert(dataKey + [index]).
У меня нет метода insert в Set, только add.
Старый 30.10.2015, 18:27   #5  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
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  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,652 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от demianimp Посмотреть сообщение
Друзья, если есть идеи по улучшению алгоритмы, то говорите. Буду рад узнать что-то новое.
Угу. Таблица называется. С индексом.

На всякий случай напомню, что индексировать можно и временные таблицы (в любых версиях 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  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Угу. Таблица называется. С индексом.

На всякий случай напомню, что индексировать можно и временные таблицы (в любых версиях Axapta)

Но если вместо Set использовать индексированную таблицу будет еще проще

Владимир Максимов , большое спасибо за разнесения.

Теперь включу нуба

А как из табличной переменой или set выдернуть медиану?
Перебирать через цикл и останавливаться на нужной записи?
Старый 31.10.2015, 06:07   #8  
macklakov is offline
macklakov
NavAx
Аватар для macklakov
 
2,129 / 916 (35) +++++++
Регистрация: 03.04.2002
Цитата:
Сообщение от demianimp Посмотреть сообщение
А как из табличной переменой выдернуть медиану?
Перебирать через цикл и останавливаться на нужной записи?
Как в обычном sql. Через count находишь количество записей, а потом while-ом отматываешь до нужной. По сравнению с quickSort должно быть гораздо быстрее искаться. Главное данные изначально в индексированную таблицу пихать, минуя стадию container-а.
__________________
Isn't it nice when things just work?
За это сообщение автора поблагодарили: mazzy (2), demianimp (1).
Старый 31.10.2015, 21:20   #9  
Raven Melancholic is offline
Raven Melancholic
Участник
Аватар для Raven Melancholic
Самостоятельные клиенты AX
Лучший по профессии 2015
 
2,158 / 1286 (47) ++++++++
Регистрация: 21.03.2005
Адрес: Москва-Петушки
Цитата:
Сообщение от demianimp Посмотреть сообщение
Добрый день.
Спешу поделиться алгоритмом поиска медины.
Немного теории:
Ну если у Вас есть время на теорию, то можете попробовать вместо быстрой сортировки другие варианты. В приложенном классе есть разные варианты сортировки. В качестве данных правда не контейнер, а какой-либо класс, реализующий определенный интерфейс.
Попробуйте, поделитесь результатами исследования.
Вложения
Тип файла: xpo SharedProject_TestSort.xpo (42.7 Кб, 463 просмотров)
За это сообщение автора поблагодарили: demianimp (1).
Старый 02.11.2015, 09:12   #10  
axm2013
Гость
 
n/a
Цитата:
Сообщение от demianimp Посмотреть сообщение
ArrayList == System.Collections.ArrayList?

У меня при ArrayList.add() с разными типами. Метод ArrayList.sort() в ошибку падает.
Да.
А почему у вас ArrayList.add() с разными типами? Если смотреть ваше преобразование то any2real как бы сводит все к одному типу.
Сортировка на real у меня выполняется без ошибок.
Подозреваю что в силу кучи причин это будет быстрее + корректнее чем самописки сортировки.
Старый 02.11.2015, 13:05   #11  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Цитата:
Сообщение от axm2013 Посмотреть сообщение
Да.
А почему у вас ArrayList.add() с разными типами? Если смотреть ваше преобразование то any2real как бы сводит все к одному типу.
Сортировка на real у меня выполняется без ошибок.
Подозреваю что в силу кучи причин это будет быстрее + корректнее чем самописки сортировки.
Действительно удобнее через ArrayList. Я правильно понимаю, что он работает только с типом real? Или он по первому arrayList.Add() определяет тип?
Старый 02.11.2015, 13:27   #12  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Вот новый код алгоритм поиска с 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  
axm2013
Гость
 
n/a
Цитата:
Сообщение от demianimp Посмотреть сообщение
Действительно удобнее через ArrayList. Я правильно понимаю, что он работает только с типом real? Или он по первому arrayList.Add() определяет тип?
Как подозреваю фактически без дополнительных усилий он будет сравнивать любые подобные данные (строки к примеру или числа)
Старый 02.11.2015, 17:02   #14  
Raven Melancholic is offline
Raven Melancholic
Участник
Аватар для Raven Melancholic
Самостоятельные клиенты AX
Лучший по профессии 2015
 
2,158 / 1286 (47) ++++++++
Регистрация: 21.03.2005
Адрес: Москва-Петушки
Цитата:
Сообщение от demianimp Посмотреть сообщение
Действительно удобнее через ArrayList. Я правильно понимаю, что он работает только с типом real? Или он по первому arrayList.Add() определяет тип?
Он работает с любым простым типом NET. В принципе, даже с разными типами должен работать, если они совместимы между собой. Из C# можно заставить его работать с любым типом, реализовав свой ICompare. Из DAX, понятно, ICompare не реализуешь, поэтому придется обойтись стандартными.
Теги
axapta, медиана, ax2009

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Как сделать в lookup поиск по нескольким полям Jurezzz DAX: Программирование 6 31.05.2013 10:45
Поиск набором в выпадающем списке.. propeller DAX: Программирование 0 04.04.2011 17:31
"поиск" braathe DAX: Программирование 6 24.03.2006 13:07
Поиск по подстроке JohNick DAX: Программирование 8 06.03.2004 22:24
Поиск по полю временной таблицы Swetik DAX: Программирование 2 10.12.2003 11:35

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 07:32.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.