(STL LIST SORT) Сортировка по некольким критериям
От: tatsu  
Дата: 18.07.09 18:28
Оценка:
Здравствуйте!
Столкнулся с такой проблемой при сортировке списка. %-)

Есть структура:

struct PackObject
{
    bool            Placed;         // Помещен ли на карту текстур
    string          SceneAlias;     // Имя сцены

    string          TexFile;
    int             TexWidth;
    int             TexHeight;
    bool            TexMipMap;
    bool            TexGray;
    bool            TexJpeg;

    string          ObjAlias;          // Имя родительского объекта
    TRect           ObjRect;
    int             AniFrameNumber;    // Порядковый номер кадра
    int             AniFrames;
    int             AniFramesPerLine;
};


А также контейнер list, элемент которого задан соответсвующей структурой.
typedef list<PackObject>               PackObjectsArray;
typedef list<PackObject>::iterator     PackObjectsIterator;


Требуется отсортировать данный контейнер наполненый некой информацией по
1) Имени сцены "SceneAlias"
2) Аттрибутам текстуры TexMipMap;TexGray;TexJpeg;
3) По размерам текстуры TexWidth; TexHeight;

ЭТО НЕ ОЗНАЧЕТ СДЕЛАТЬ 3 РАЗНЫХ СОРТИРОВКИ!!! ЭТО ЗНАЧИТ ЧТОБЫ СВЕРХУ ВНИХ ОБЪЕКТЫ БЫЛИ ОТСОРТИРОВАННЫ ПО ДАННЫМ КРИТЕРИЯМ!

Т.е.
1) Scene1 JPEG MIPMAP GRAY 1000x900
2) Scene1 JPEG MIPMAP GRAY 800x900
3) Scene1 JPEG MIPMAP 1000x900
4) Scene1 JPEG MIPMAP 700x700
5) Scene1 JPEG GRAY 1500x1500
6) Scene1 JPEG GRAY 700x700
7) Scene1 JPEG 2000x700
8) Scene1 JPEG 1000x700
8 ) Scene1 100x100
9 ) Scene1 100x50
10) Scene2 .......

Т.е. номера пунктов 3-ех аттрибутов являются как бы приоритетами (важностью) 1) 2) 3)


[size=4]НО ПРОБЛЕМА НЕ В ТОМ КАК ОТСОРТИРОВАТЬ!!!!!![/size]

Проблема заключается в том что функция PREDICATE для списка LIST отказывается сортировать корректно его элементы!

Вот один из испробованных мною вариантов PREDICATE функции (до этого я пытался делать эту функцию разными способами в том числе перегрузкой скобок () и перегрузкой знака ">" )

bool PackPred(PackObject &obj1, PackObject &obj2)
{
    bool result = false;

    if (sortmem_apartscenes)
    {
        // Cортируем по имени сцены в алфавитном порядке
        string str1 = obj1.SceneAlias;
        string str2 = obj2.SceneAlias;
        size_t minlen = (str1.length() > str2.length()) ? str2.length() : str1.length();
        for (size_t i = 0; i < minlen; i++)
        {
            if (str1[i] > str2[i])
            {
                result = true;
                break;
            }
        }
        if (str1.length() > str2.length()) result = true;
    }

    // Объекты одной сцены сортируем по параметрам текстуры
    if (sortmem_apartjpeg)
    {
        if ((obj1.TexJpeg) && (!obj2.TexJpeg))  result = true;
    }

    if ((obj1.TexMipMap) && (!obj2.TexMipMap)) result = true;
    if ((obj1.TexGray)   && (!obj2.TexGray))   result = true;

    // Возвращаем результат сравнения размеров
    int width1  = obj1.TexWidth;
    int height1 = obj1.TexHeight;
    int width2  = obj2.TexWidth;
    int height2 = obj2.TexHeight;
    // Хотябы один размер был больше
    if ( ((width1  > width2) && (width1  > height2)) ||
         ((height1 > width2) && (height1 > height2)) ) result = true;*/    
    return result;
};


Пояснения!
1) Переменные bool sortmem_apartscenes и bool sortmem_apartjpeg являются глобальными. Увы от них избавится не вышло а добавлять еще 3 варианта сортировки было бы некрасиво. Перед сортировкой эти переменные устанавливаются в нужное значение.

2) Переменные TexJpeg TexMipMap и TexGray пробывал сравнивать знаком > но все равно безрезультатно.

3) bool result — это якобы варинт написания функции как в Дельфи. Просто во время отладки я заметил очень странную весчь. Оказывается в PREDICATE функции при к примеру "return true" не происходит выход из функции а продолжает обрабатывать всею последующие команды =-O Я не понимать что это за баг?

4) Если проверять по отдельности то разделив на 3-и блока всю функцию сортировки

— мы получим что 1-ый блок с сортировкой по алфавиту, не выполняется (хотя список элементов string успешно сортирует имена файлов но только в другом участке в другом контейнере в моей работе)

— 2 блок кода выполняется только отдельно к примеру только сортировка по JPEG аттрибуту.

— 3 блок сортироки по размерам блестяще выполняется.

ПРИТОМ! Если по всем 3 блокам одновременно я пытаюсь сортировать данный список то у меня получается что
1) По именам сцен сортирует но имена сцен и без того изначально были уже в отсортированном виде еще при добавлении в список элементов (отсортировать в обратном порядке при изменении знака > на знак < ничего не меняется но если блок убрать то порядок теряется)
2) Также сортирует по именьшению сверху вниз размеров текстур.
Аттрибуты же текстур остаются в произвольном порядке....


Как это можно вылечить. Может кто уже сталкивался со сложными сортировками?
Re: (STL LIST SORT) Сортировка по некольким критериям
От: VoidEx  
Дата: 18.07.09 18:53
Оценка:
Здравствуйте, tatsu, Вы писали:

Вам таки надо написать правильно предикат и всё, если я правильно понял.
Что-то типа:
bool operator () (object const & l, object const & r)
{
  return (l.SceneAlias <= r.SceneAlias) &&
    // прочие условия
    (l.TexWidth <= r.TexWidth) &&
    (l.TexHeight < r.TexHeight);
}
Re: (STL LIST SORT) Сортировка по некольким критериям
От: Jenkas Россия  
Дата: 18.07.09 19:11
Оценка:
Здравствуйте, tatsu, Вы писали:

T>ЭТО НЕ ОЗНАЧЕТ СДЕЛАТЬ 3 РАЗНЫХ СОРТИРОВКИ!!! ЭТО ЗНАЧИТ ЧТОБЫ СВЕРХУ ВНИХ ОБЪЕКТЫ БЫЛИ ОТСОРТИРОВАННЫ ПО ДАННЫМ КРИТЕРИЯМ!


T>Т.е.

T>1) Scene1 JPEG MIPMAP GRAY 1000x900
T>2) Scene1 JPEG MIPMAP GRAY 800x900
T>3) Scene1 JPEG MIPMAP 1000x900
T>4) Scene1 JPEG MIPMAP 700x700
T>5) Scene1 JPEG GRAY 1500x1500
T>6) Scene1 JPEG GRAY 700x700
T>7) Scene1 JPEG 2000x700
T>8) Scene1 JPEG 1000x700
T>8 ) Scene1 100x100
T>9 ) Scene1 100x50
T>10) Scene2 .......

T>Т.е. номера пунктов 3-ех аттрибутов являются как бы приоритетами (важностью) 1) 2) 3)



В вашей функции есть ошибка. Продолжать проверку по след. приоритетному атрибуту стоит только если предидущик атрибуты были равны.

Попробуйте так:

bool PackPred(PackObject &obj1, PackObject &obj2)
{
    if (sortmem_apartscenes)
    {
        string str1 = obj1.SceneAlias;
        string str2 = obj2.SceneAlias;
        if (str1 > str2) {
            return true; //немедленый выход, если больше
        } 
        if (str1 < str2) {
            return false; //немедленый выход, если меньше
        } 
    }
    //если равно то делаем проверку по след. параметру
    if (sortmem_apartjpeg)
    {
        // Объекты одной сцены сортируем по параметрам текстуры
        if ((obj1.TexJpeg) && (!obj2.TexJpeg))  {
            return true; //немедленый выход, если больше
        }
        if ((!obj1.TexJpeg) && (obj2.TexJpeg))  {
            return false; //немедленый выход, если меньше
        }
    }
    //если равно то делаем проверку по след. параметру
    if ((obj1.TexMipMap) && (!obj2.TexMipMap))  {
        return true; //немедленый выход, если больше
    }
    if ((!obj1.TexMipMap) && (obj2.TexMipMap))  {
        return false; //немедленый выход, если меньше
    }    
    //если равно то делаем проверку по след. параметру
    if ((obj1.TexGray) && (!obj2.TexGray))  {
        return true; //немедленый выход, если больше
    }
    if ((!obj1.TexGray) && (obj2.TexGray))  {
        return false; //немедленый выход, если меньше
    }
    //если равно то делаем проверку по след. параметру
    // Возвращаем результат сравнения размеров
    int width1  = obj1.TexWidth;
    int height1 = obj1.TexHeight;
    int width2  = obj2.TexWidth;
    int height2 = obj2.TexHeight;
    // Хотябы один размер был больше
    if ( ((width1  > width2) && (width1  > height2)) ||
         ((height1 > width2) && (height1 > height2)) ) 
         return true; //немедленый выход, если больше
    //и т.д.
    return false;
};
Re: (STL LIST SORT) Сортировка по некольким критериям
От: sraider http://dvinogradov.blogspot.com
Дата: 18.07.09 20:24
Оценка: 1 (1)
T>Требуется отсортировать данный контейнер наполненый некой информацией по
T>1) Имени сцены "SceneAlias"
T>2) Аттрибутам текстуры TexMipMap;TexGray;TexJpeg;
T>3) По размерам текстуры TexWidth; TexHeight;

А оно потом удобно будет такой код сопровождать? Отлаживать? Попробуй KISS.

Как-то так:
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>

bool PackPred(PackObject &o1, PackObject &o2)
{
  return
    boost::tie(o1.SceneAlias, o1.TexMipMap, o1.TexGray, o1.TexJpeg, o1.TexWidth, o1.TexHeight) <
    boost::tie(o2.SceneAlias, o2.TexMipMap, o2.TexGray, o2.TexJpeg, o2.TexWidth, o2.TexHeight);
}


Точнее, в твоем случае как-то вот так:
bool PackPred(PackObject &o1, PackObject &o2)
{
  string NotSortAlias;
  bool NotSortJpeg;
  int o1TexSize = o1.TexWidth + o1.TexHeight;
  int o2TexSize = o2.TexWidth + o2.TexHeight;

  return
    boost::tie(sortmem_apartscenes ? o1.SceneAlias : NotSortAlias, o1.TexMipMap, o1.TexGray, sortmem_apartjpeg ? o1.TexJpeg : NotSortJpeg, o1TexSize) <
    boost::tie(sortmem_apartscenes ? o2.SceneAlias : NotSortAlias, o2.TexMipMap, o2.TexGray, sortmem_apartjpeg ? o2.TexJpeg : NotSortJpeg, o2TexSize);
}
Re[2]: (STL LIST SORT) Сортировка по некольким критериям
От: tatsu  
Дата: 18.07.09 20:25
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Здравствуйте, tatsu, Вы писали:


VE>Вам таки надо написать правильно предикат и всё, если я правильно понял.

VE>Что-то типа:
VE>
VE>bool operator () (object const & l, object const & r)
VE>{
VE>  return (l.SceneAlias <= r.SceneAlias) &&
VE>    // прочие условия
VE>    (l.TexWidth <= r.TexWidth) &&
VE>    (l.TexHeight < r.TexHeight);
VE>}
VE>


Пробывал вот так и не помогло ((


struct PackPred : public greater<PackObject>
{
    bool operator()(PackObject &obj1, PackObject &obj2) const
    { 

            // Содержание что и выше 

    }
};
Re[2]: (STL LIST SORT) Сортировка по некольким критериям
От: tatsu  
Дата: 18.07.09 20:33
Оценка:
Кажется это то что именно нужно. Я еще не пробывал но по реакции своего мозга на ваш ответ дкмаю что именно это и было пакой в спицах велосипеда

Преогромнейшие благодарности в Ваш адрес! Вы бог! Спасибо! Пойду исправляться.

И единственный вопрос который тут же возник..
Я уже в сообщении писал что "return" при отладке почемуто не вызывал мгновенный выход из функции сравнения PREDICATE
Вы же привели код где как разтаки и используются return для мгновенного выхода.. Как быть.. Это глюк отладки или особенности использования PREDICATE функции может быть вы подскажите? Огромное спасибо еще раз!
Re[2]: (STL LIST SORT) Сортировка по некольким критериям
От: tatsu  
Дата: 18.07.09 20:37
Оценка:
Спасибо но кажется ошибку уже нашли.
А насчет новейших технологий мне пока еще рано..
Мне пока еще учить и учить основы STL и расти расти большим))
Boost обязательно буду постигать а пока для меня это матерные слова Х))
Все равно большое спасибо за направление и советы.. буду учится
Re[2]: (STL LIST SORT) Сортировка по некольким критериям
От: tatsu  
Дата: 18.07.09 21:26
Оценка:
Да! Это работает!
Огромое спасибо!
Re[3]: (STL LIST SORT) Сортировка по некольким критериям
От: Jenkas Россия  
Дата: 19.07.09 08:59
Оценка:
Здравствуйте, tatsu, Вы писали:

T>Кажется это то что именно нужно. Я еще не пробывал но по реакции своего мозга на ваш ответ дкмаю что именно это и было пакой в спицах велосипеда


T>Преогромнейшие благодарности в Ваш адрес! Вы бог! Спасибо! Пойду исправляться.


T>И единственный вопрос который тут же возник..

T>Я уже в сообщении писал что "return" при отладке почемуто не вызывал мгновенный выход из функции сравнения PREDICATE
T>Вы же привели код где как разтаки и используются return для мгновенного выхода.. Как быть.. Это глюк отладки или
особенности использования PREDICATE функции может быть вы подскажите? Огромное спасибо еще раз!

Рад помочь.

А на счёт return — вообще, философия програмирования не любит таких "немедленных" return-ов, но если же он используется, то работать будет всегда =). Данная задача это позволяет, и даже приветствует, но надо стараться писать код с одним выходом и одним входом =)

Удачи!
Re[3]: (STL LIST SORT) Сортировка по некольким критериям
От: Caracrist https://1pwd.org/
Дата: 19.07.09 19:09
Оценка:
Здравствуйте, tatsu, Вы писали:

T>Кажется это то что именно нужно. Я еще не пробывал но по реакции своего мозга на ваш ответ дкмаю что именно это и было пакой в спицах велосипеда


T>Преогромнейшие благодарности в Ваш адрес! Вы бог! Спасибо! Пойду исправляться.


T>И единственный вопрос который тут же возник..

T>Я уже в сообщении писал что "return" при отладке почемуто не вызывал мгновенный выход из функции сравнения PREDICATE
T>Вы же привели код где как разтаки и используются return для мгновенного выхода.. Как быть.. Это глюк отладки или особенности использования PREDICATE функции может быть вы подскажите? Огромное спасибо еще раз!

return вызывает деструкторы всех инициализированных локальных объектов.
~~~~~
~lol~~
~~~ Single Password Solution
Re[2]: (STL LIST SORT) Сортировка по некольким критериям
От: -MyXa- Россия  
Дата: 20.07.09 16:46
Оценка:
Здравствуйте, sraider, Вы писали:

S>
S>bool PackPred(PackObject &o1, PackObject &o2)
S>{
S>  string NotSortAlias;
S>  bool NotSortJpeg;
S>  int o1TexSize = o1.TexWidth + o1.TexHeight;
S>  int o2TexSize = o2.TexWidth + o2.TexHeight;

S>  return
S>    boost::tie(sortmem_apartscenes ? o1.SceneAlias : NotSortAlias, o1.TexMipMap, o1.TexGray, sortmem_apartjpeg ? o1.TexJpeg : NotSortJpeg, o1TexSize) <
S>    boost::tie(sortmem_apartscenes ? o2.SceneAlias : NotSortAlias, o2.TexMipMap, o2.TexGray, sortmem_apartjpeg ? o2.TexJpeg : NotSortJpeg, o2TexSize);
S>}


+1
Отличный способ! Мы тоже так предикаты можем. Ещё sortmem_apartscenes в поле функтора закатать, но это мелочи.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[2]: (STL LIST SORT) Сортировка по некольким критериям
От: pvirk Россия  
Дата: 24.07.09 09:11
Оценка:
Здравствуйте, sraider, Вы писали:

S>Точнее, в твоем случае как-то вот так:

S>
S>bool PackPred(PackObject &o1, PackObject &o2)
S>{
S>  string NotSortAlias;
S>  bool NotSortJpeg;
S>  int o1TexSize = o1.TexWidth + o1.TexHeight;
S>  int o2TexSize = o2.TexWidth + o2.TexHeight;

S>  return
S>    boost::tie(sortmem_apartscenes ? o1.SceneAlias : NotSortAlias, o1.TexMipMap, o1.TexGray, sortmem_apartjpeg ? o1.TexJpeg : NotSortJpeg, o1TexSize) <
S>    boost::tie(sortmem_apartscenes ? o2.SceneAlias : NotSortAlias, o2.TexMipMap, o2.TexGray, sortmem_apartjpeg ? o2.TexJpeg : NotSortJpeg, o2TexSize);
S>}


Пипец, вместо написания простейшей сравнялки, такой огород с бустом городить!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.