Vinícius
Vinícius

Reputation: 15718

Sort struct int members

What would be a C++ way to sort structs with different amount of integer members. (Notice they're always ints)

Suppose I have a struct with 3 ints in it and I want to sort them:

void Sort(int& x, int& y, int& z)
{
    //do stuff
    if(x > y >...etc) x = y z=tmp //etc etc
}

struct Foo
{
    int a {1};
    int b {3};
    int c {2};
};


int main()
{
    Foo foo;
    Sort(foo.a, foo.b, foo.c);
}

I could also pass Foo as an argument instead of 3 ints of course: void Sort(Foo& foo)

But suppose I have another struct with different amount of integers:

struct Bar
{
    int a{7};
    int b{8};
};

I would have to create another function for sorting:

void Sort(int& y, int& x) {}...

or even just for the struct Bar itself:

void Sort(Bar& bar) {};

Now, I've got many structs and all of them contain different amount of ints as data members. What is an overall way to sort the integer struct members in decreasing order?

-edit

I'll edit the question because maybe my fundamental approach to this is wrong. In my original problem I have two structs:

struct PlayerPrince {
    int highCard;
    int middleCard;
};
struct PlayerPrincess {
    int highCard;
    int middleCard;
    int lowCard;
};

The values of the data members will be assigned accordingly to user input order. It can only be assured that int highCard will only be the highest card after the struct is sorted.

struct PlayerPrince does not need to have a lowCard and I would like to sort the members of each struct without defining multiple functions. If there is a better design approach to the problem (as stated in the comments) I'd be glad to know.

Upvotes: 0

Views: 358

Answers (1)

David C. Rankin
David C. Rankin

Reputation: 84541

As mentioned by @WhozCraig in the comments, the key is not to declare individual integer values within your struct like int a; int b; int c;, but instead use a container such as std::array (if you have a fixed number of int in that type struct), or use std::vector (and add as many int values as you need to the vector)

std::sort provided by the <algorithm> header then makes sorting on int trivial as the default-compare function can be used without having to specify any special function of your own. Approaching the problem in this manner allows you to sort any number of integers contained withing your std::array or std::vector member regardless of how many integers are contained by using the standard .begin() and .end() iterators provided by the container.

Using std::array

For example, if you want to sort a struct with a fixed 3-integer array, you can simply do:

#include <iostream>
#include <array>
#include <algorithm>

struct Foo {    /* struct Foo with std::array<int, 3> instead of 3 int variables */
    std::array<int, 3> ints;
};

int main (void) {

    Foo foo;                    /* instance of foo */

    foo.ints.at(0) = 1;         /* add 3-int to array ints */
    foo.ints.at(1) = 3;
    foo.ints.at(2) = 2;

    /* sort foo.ints using default compare */
    std::sort (foo.ints.begin(), foo.ints.end());

    for (auto& i : foo.ints)    /* output sorted foo.ints */
        std::cout << " " << i;
    std::cout << '\n';
}

Using std::vector

To use any number of integers in your struct simply replace std::array with std::vector and use .push_back() to add as many integers to your vector as you like. The case above becomes:

#include <iostream>
#include <vector>
#include <algorithm>

struct Foo {    /* struct Foo with std::vector<int> instead of separate integers */
    std::vector<int> ints;
};

int main (void) {

    Foo foo;                    /* instance of foo */

    foo.ints.push_back(1);      /* add 3-int to vector ints */
    foo.ints.push_back(3);
    foo.ints.push_back(2);

    /* sort foo.ints using default compare */
    std::sort (foo.ints.begin(), foo.ints.end());

    for (auto& i : foo.ints)    /* output sorted foo.ints */
        std::cout << " " << i;
    std::cout << '\n';
}

(note: with std::vector you can add 1-integer or 100000-integers and the only thing that changes is the number of times you call foo.ints.push_back(x);)

Using std::greater<T>() for Descending Sort

The <functional> header provides several standard comparisons such as std::greater<T>(), std::less<T>(), std::less_equal<T>(), etc.. To sort the array or vector is descending our you can use std::greater<int>() as the compare function, e.g.

    /* sort foo.ints using std::greater<T>() compare */
    std::sort (foo.ints.begin(), foo.ints.end(), std::greater<int>());

Example Use/Output

In both cases using the default sort the output is the same:

$ ./bin/sortfooints
 1 2 3

(using std::greater<int>() would result in 3 2 1)

Look things over and let me know if you have further questions.

Upvotes: 1

Related Questions