sort list

Started by
22 comments, last by Servant of the Lord 7 years, 9 months ago

Hi

I want to sort by color. Simply lower before higher numbers, only int 1-3

Ausfalllinie[0].push_back(Ausfaelle(20,1,2,APdiscon,20, "autopilot_disconnect"));
Ausfalllinie[1].push_back(Ausfaelle(21,1,1,APtrimDo,1*20, "autopilot_trim_down"));
Ausfalllinie[2].push_back(Ausfaelle(22,1,3,Fuel,2*20, "fuel_pump_on"));

...

...

The class.h is:

class Ausfaelle {
public:
int index, active, color, height;
float drValue;
std::string label;
Ausfaelle(int index, int active, int color, float drValue, int height, std::string label);

};

and the readout:

for( int x = 0; x < 10; x = x + 1 )
{
for (std::list<Ausfaelle>::iterator it=Ausfalllinie[x].begin(); it != Ausfalllinie[x].end(); ++it)
{
Ausfaelle test = *it;

...

...

Many thanks

Advertisement

std::sort() does this for you. You can pass it a custom sort function.

The syntax is:


 std::sort(begin(myList), end(myList), YourSortFunction);

Using a lambda it can look like this:


struct MyStruct
{
   float value;
};

std::list<MyStruct> myList;

std::sort(begin(myList), end(myList),
[](const MyStruct &structA, const MyStruct &structB)
{
    return (structA.value < structB.value); //Replace with your sort criteria.
});

Note: Instead of using container.begin() and container.end(), the newest guidelines say to use std::begin(container) and std::end(container). It's more flexible, and works with things like normal arrays, and so on.

In the majority of situations where you'll be using it, you won't have to type std::, because the compiler can resolve that namespace for you on the begin()/end() functions.

Have you tried std::sort?

std::sort(
   std::begin(Ausfalllinie[x]),
   std::end(Ausfalllinie[x]),
   [](const Ausfaelle& a, const Ausfaelle& b)
   {
       return a.color < b.color;
   });
edit: Ninja'd.

No, std::sort requires random access iterators. std::list only provides bidirectional iterators, which means you can't use them with std::sort. Use std::list::sort instead.

blah :)

No, std::sort requires random access iterators. std::list only provides bidirectional iterators, which means you can't use them with std::sort. Use std::list::sort instead.

*facepalm* - Mea culpa.

I almost always use std::vector - I forgot about the iterator requirements.

No, std::sort requires random access iterators. std::list only provides bidirectional iterators, which means you can't use them with std::sort. Use std::list::sort instead.


*facepalm* - Mea culpa.
I almost always use std::vector - I forgot about the iterator requirements.


Likewise. std::list is not something I see often, and for pretty good reason. I would be curious to know why OP is using std::lists here.

Hi

I have the image scrolling but only want each image once. With the first on top

for( int x = 0; x < 10; x = x + 1 )
{
for (std::list<Ausfaelle>::iterator it=Ausfalllinie[x].begin(); it != Ausfalllinie[x].end(); ++it)
{
Ausfaelle test = *it;

if (test.drValue >= 0.2){

...

show image with x as height.

...

Cant' wrap my head around those two for. Also still couldn't get the list sorted by color.

Many thanks

First, you probably should be using std::vector, unless you have a reason why you need to use std::list.

Use 'auto' instead of 'std::list<Ausfaelle>::iterator', it'll make your code easier to read.

Also use 'range-for' for() loops if you want to iterate over every element in a container (I'll so an example of this below).

Run this code to understand how two nested for() loops work. Currently you are doing each image 10 times.

I'm not 100% sure what you are going for, but I think this is closer to what you are wanting:


int x = 0; //Initialize 'x'.

//This is a range-for(). It loops over every element of 'Ausfalllinie',
//and makes 'ausfaelle' be a reference to each element.
for(const Ausfaelle &ausfaelle : Ausfalllinie) 
{
    if(ausfaelle.drValue >= 0.2f)
    {
        //...
    }
    
    //Increment 'x', so each 'x' is larger than than the previous loop/iteration's 'x'.
    ++x; //Same as x = (x + 1);
}

As for sorting your container, if you use a std::vector, it should look like this:


std::sort(begin(Ausfalllinie), end(Ausfalllinie),
[](const Ausfaelle &ausfaelle1, const Ausfaelle &ausfaelle2)
{
    return (ausfaelle1.color < ausfaelle2.color); //Return true if 'ausfaelle1' should be sorted before 'ausfaelle2'.
});

If you use a std::list, it should look like this:


Ausfalllinie.sort([](const Ausfaelle &ausfaelle1, const Ausfaelle &ausfaelle2)
{
    return (ausfaelle1.color < ausfaelle2.color); //Return true if 'ausfaelle1' should be sorted before 'ausfaelle2'.
});

Thanks now the sorting is still not working. Also the first should be on top but I guess this will work after sort as well?

for( int x = 0; x < 10; x = x + 1 )
{
for (std::list<Ausfaelle>::iterator it=Ausfalllinie[x].begin(); it != Ausfalllinie[x].end(); ++it)
{

Ausfaelle test = *it;

Ausfalllinie[x].sort(compare(Ausfaelle &test, Ausfaelle &test2));

...

I get this error:

Multiple markers at this line
- ‘test2’ was not declared in this scope

- expected primary-expression before ‘&’

defined alike:

bool compare (Ausfaelle &ausfaelle1, Ausfaelle &ausfaelle2)
{
return ( ausfaelle1.color < ausfaelle2.color );
}

Many thanks

I get this error:
Multiple markers at this line
- ‘test2’ was not declared in this scope
- expected primary-expression before ‘&’

'test2' was not declared in the scope. The error message is not ambiguous. You can not just take the address of an undeclared variable like that.

What you want to do is pass the function itself, not call the function.

Ausfalllinie.sort(compare);

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement