Форум программистов, компьютерный форум CyberForum.ru

HOWTO: сортировка массива структур по произвольному полю - C++

Восстановить пароль Регистрация
 
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
09.07.2013, 18:53     HOWTO: сортировка массива структур по произвольному полю #1
Вот тут товарищ навел на размышления, а как же собственно сортировать по произвольному полю?
C++
1
2
3
4
5
struct myStruct{
    int m1;
    string m2;
    //etc...
};
мне представляется такой вариант поле для сравнения определяется предварительной установкой параметра fobj:
C++
1
2
3
4
vector<myStruct> v;
Compare fobj;
fobj.opt = 1;// <---???
sort(v.begin(),v.end(),fobj);
где предикат:
C++
1
2
3
4
5
6
7
8
9
10
struct Compare:public binary_function<myStruct&,myStruct&, bool >{
        int opt;    
        bool operator()(const myStruct &a,const myStruct &b ) {
            switch(opt){
                case 1:{ return a.m1 < b.m1; break;}
                case 2:{ return a.m2 < b.m2; break;}
                //etc...
            }
        }
};
Это выглядит несколько ущербно, к тому же при большом количестве полей для каждого нужно будет описывать однообразные операции.
Как сделать лучше (или может я вообще не в ту сторону смотрю) ?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.07.2013, 18:53     HOWTO: сортировка массива структур по произвольному полю
Посмотрите здесь:

C++ Сортировка структур по полю
C++ Сортировка массива(вектора)структур по одному полю
Сортировка массива структур по выбранному полю с помощью алгоритма std::sort C++
Файл структур: сортировка по выбираемому пользователем полю C++
C++ Сортировка массива структур через switch по любому полю
C++ Сортировка массива структур по определенному полю
C++ Сортировка массива (вектора) структур по заданному полю
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6230 / 2959 / 287
Регистрация: 04.12.2011
Сообщений: 7,896
Записей в блоге: 3
09.07.2013, 19:23     HOWTO: сортировка массива структур по произвольному полю #2
Vladimir., мне самому интересно. Вот в Вашем примере со switch() можно бы прямо оператор сравнения в myStruct определить, тогда и без предиката получится, но и в этом случае нужно поле opt и его надо устанавливать. Можно функторов понаписать. Предикат тоже хорошая штука.
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
09.07.2013, 19:24     HOWTO: сортировка массива структур по произвольному полю #3
курите stl евский sort с функцией сравнения... больше вам начего не нужно.
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6230 / 2959 / 287
Регистрация: 04.12.2011
Сообщений: 7,896
Записей в блоге: 3
09.07.2013, 19:29     HOWTO: сортировка массива структур по произвольному полю #4
Цитата Сообщение от Kukurudza Посмотреть сообщение
курите stl евский sort с функцией сравнения... больше вам начего не нужно.
Предлагаете глобально наопределять?
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
09.07.2013, 19:32     HOWTO: сортировка массива структур по произвольному полю #5
ну это вроде как обычный случай. я к сожалению не знаю как это делают трупрогеры. мне приходилось делать 2-3 функции сравнения, как в вашем случае, я этим ограничивался. меня это устраивало.
NoMasters
Псевдослучайный
1740 / 1083 / 70
Регистрация: 13.09.2011
Сообщений: 3,103
09.07.2013, 20:21     HOWTO: сортировка массива структур по произвольному полю #6
2013 год на дворе, лямбды же есть:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct some
{
    int one;
    std::string two;
};
 
std::vector<some> v;
auto comp_by_one = [](const some &a, const some &b)-> bool {return a.one > b.one;};
auto comp_by_two = [](const some &a, const some &b)-> bool {return a.two > b.two;};
...
std::sort(v.begin(), v.end(), comp_by_one);
...
std::sort(v.begin(), v.end(), comp_by_two);
...
Thinker
Эксперт C++
 Аватар для Thinker
4216 / 2190 / 150
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
09.07.2013, 20:24     HOWTO: сортировка массива структур по произвольному полю #7
Цитата Сообщение от Kukurudza Посмотреть сообщение
курите stl евский sort с функцией сравнения... больше вам начего не нужно.
stl это, конечно, здорово, но если не разбираться в алгоритмах собственными ручками, то потом "курить" придется программистов, которые в этом разбираются
Tulosba
:)
Эксперт С++
4382 / 3225 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
09.07.2013, 21:32     HOWTO: сортировка массива структур по произвольному полю #8
Цитата Сообщение от Thinker Посмотреть сообщение
stl это, конечно, здорово, но если не разбираться в алгоритмах собственными ручками, то потом "курить" придется программистов, которые в этом разбираются
Но не писать же каждый раз свой собственный qsort. Есть инструмент (stl) и надо уметь им пользоваться.
Thinker
Эксперт C++
 Аватар для Thinker
4216 / 2190 / 150
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
09.07.2013, 21:41     HOWTO: сортировка массива структур по произвольному полю #9
Цитата Сообщение от Tulosba Посмотреть сообщение
Но не писать же каждый раз свой собственный qsort. Есть инструмент (stl) и надо уметь им пользоваться.
1. один и тот же алгоритм со временем можно написать кучей способов, используя новые техники
2. если использовать только готовые функции, не вникая в них, так можно вообще не stl изучать, а адреса it-компаний, которые занимаются разработкой программного обеспечения, и у них заказывать программы.
3. никто не говорит, что "каждый раз свой собственный qsort", а разок-другой, а то и третий, стоит, полезно
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1237 / 986 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
09.07.2013, 21:48     HOWTO: сортировка массива структур по произвольному полю #10
Я не думаю, что ТСа интересует, как писать сортировки. Он небось и так прекрасно себе представляет, как оно работает. Задача тут чисто инженерная: как описать эту сортировку как можно проще.

Обобщённую сортировку по произвольному полю написать вряд ли получится: в Си++ нет встроенной рефлексии. Так что придётся или хардкодить руками все поля (где-нибудь), или писать свою мини-рефлексию. Я бы выбрал ad hoc описание функции сравнения лямбдой, или там структуркой рядом, или поименованной структуркой в неймспейсе класса, если такое сравнение часто используется. Но если вам действительно надо сортировать по динамически выбираемому полю, то в конечном итого всё сведётся к вон тому свичу, что в первом посте (насколько он будет глубоко зарыт, зависит от паттернов головного мозга).
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
10.07.2013, 07:42     HOWTO: сортировка массива структур по произвольному полю #11
так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <string>
#include <iostream>
#include <algorithm>
 
struct st {
    int d;
    std::string s;
 
    st(const int _d, const std::string& _s) {
        d = _d;
        s = _s;
    }
 
    void print() const {
        std::cout << d << ":" << s << " ";
    }
};
 
bool intPriority(const st& v, const st& u) {
    if (v.d == u.d) {
        return (v.s < u.s);
    } else {
        return (v.d < u.d);
    }
}
 
bool stringPriority(const st& v, const st& u) {
    if (v.s == u.s) {
        return (v.d < u.d);
    } else {
        return (v.s < u.s);
    }
}
 
void printMassiv(const std::vector<st>& massiv) {
    for (auto &i: massiv) {
        i.print();
    }
    std::cout << "\n";
}
 
void sortMassivWithCriterion(std::vector<st>& massiv, const int cr) {
    switch(cr) {
        case 0: {
            std::sort(massiv.begin(), massiv.end(), intPriority);
            break;
        }
        case 1: {
            std::sort(massiv.begin(), massiv.end(), stringPriority);
            break;
        }
        default: return;
    }
    printMassiv(massiv);
}
 
int main() {
    std::vector<st> massiv;
    massiv.push_back(st(9, "a"));
    massiv.push_back(st(3, "g"));
    massiv.push_back(st(1, "i"));
    massiv.push_back(st(2, "h"));
    massiv.push_back(st(7, "c"));
    massiv.push_back(st(4, "f"));
    massiv.push_back(st(6, "d"));
    massiv.push_back(st(8, "b"));
    massiv.push_back(st(5, "e"));
    printMassiv(massiv);
 
    sortMassivWithCriterion(massiv, 0);
    sortMassivWithCriterion(massiv, 1);
 
    return 0;
}
?
Praktolock
 Аватар для Praktolock
62 / 62 / 0
Регистрация: 29.11.2011
Сообщений: 289
10.07.2013, 07:57     HOWTO: сортировка массива структур по произвольному полю #12
а чо, макросы не рулят?

Добавлено через 4 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define MYCOMPARE(a, b, member) (a.##member<b.##member)
 
struct MYSTRUCT
{
 int kolichestvo;
 double kachestvo;
};
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
 MYSTRUCT st1, st2;
 st1.kachestvo =0.4; st2.kachestvo=0.75;
 st1.kolichestvo=15; st2.kolichestvo=1;
 
 printf("%d  ", MYCOMPARE(st2, st1, kolichestvo) );
 
 system ("pause");
 return 0;
}
Добавлено через 1 минуту
Данный макрос сравнивает у двух структур члены, имя которых ему передаётся в качестве параметра. Некоторым не нравятся макросы, но это вполне себе вариант
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
10.07.2013, 08:03     HOWTO: сортировка массива структур по произвольному полю #13
курите: Чем же макрос define так плох?
при этом функции сортировки напишите?
Praktolock
 Аватар для Praktolock
62 / 62 / 0
Регистрация: 29.11.2011
Сообщений: 289
10.07.2013, 08:04     HOWTO: сортировка массива структур по произвольному полю #14
курил. мне нравится. не агитирую, просто вариант предложил
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
10.07.2013, 08:16     HOWTO: сортировка массива структур по произвольному полю #15
что то я изначально видимо плохо вник в задачу. вам "на лету" сортировки надо менять поле сортировки? или от сортировки к сортировке изменять поле?
если второе, то вам уже предложили 2 варианта: один с лямбдой, второй пост №11.
если же второе, то вообще говоря это что-то очень странное, потому как от сортировки к сортировке результаты будут не коммутативны, если я не ошибаюсь. и зависеть они будут от случайности выбора поля сравнения в настоящий момент времени. это какая-то чепуха на мой взгляд.
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
12.07.2013, 23:09  [ТС]     HOWTO: сортировка массива структур по произвольному полю #16
После чтения первоисточников, чужого кода и бесед IRL,
вывод:
практически, если количество полей невелико, удобнее всего использовать (как посоветовалNoMasters) лямбда-выражения по месту.

Всем спасибо. Решено.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.07.2013, 02:07     HOWTO: сортировка массива структур по произвольному полю
Еще ссылки по теме:

C++ Сортировка массива структур по заданному полю
C++ Сортировка массива структур по заданному полю
C++ Реализовать сортировку массива структур по заданному полю
Сортировка массива структур по одному полю C++
C++ Сортировка массива структур по одному полю

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
rangerx
1918 / 1527 / 139
Регистрация: 31.05.2009
Сообщений: 2,886
13.07.2013, 02:07     HOWTO: сортировка массива структур по произвольному полю #17
Цитата Сообщение от Vladimir. Посмотреть сообщение
а как же собственно сортировать по произвольному полю?
вопрос по синтаксису/типам
Yandex
Объявления
13.07.2013, 02:07     HOWTO: сортировка массива структур по произвольному полю
Ответ Создать тему
Опции темы

Текущее время: 16:31. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru