Thread: Sorting vector of structs based on struct member value

  1. #1
    Registered User
    Join Date
    Jun 2013
    Posts
    25

    Sorting vector of structs based on struct member value

    Heya!

    I've got a vector which holds structs of coordinates like this:

    Code:
    struct Coordinate{
    
        double x,y;
    
    };
    
    std::vector<Coordinate>incCoords
    How can I sort my vector struct based on its y values?

    Basically I'm looking for the function

    Code:
    sort(incCoords.begin(), incCoords.end());
    but sorting the actual struct inside the vector based on the y value.

    My attempt:

    Code:
    bool Tree::getLowerY(Coordinate &a, Coordinate &b) 
    { 
    return a.y < b.y; 
    } 
    
    std::sort(incCoords.begin(), incCoords.end(), getLowerY);
    Doesn't work, getting the following error:
    no matching function for call to 'sort(std::vector<Coordinate>::iterator, std::vector<Coordinate>::iterator, <unresolved overloaded function type>)'


    But my approach may be way off :/

    Thanks in advance!!

  2. #2
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    257
    In your getLowerY() Function, the arguments should be passed by const reference.

  3. #3
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    257
    Also, is Tree a class? If so, the getLowerY() method must be static.

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    The compatator, `getLowerY', should also be a non-member function.

    Soma

  5. #5
    Registered User FortranLevelC++'s Avatar
    Join Date
    May 2013
    Location
    United States
    Posts
    81
    It seems that this question about std::sort() is similar to the other thread (yesterday) about the application of std::max_element() to a vector of structs, which got resolved with the help of the same people here.
    Last edited by FortranLevelC++; 06-13-2013 at 04:36 PM.

  6. #6
    Registered User
    Join Date
    Jun 2013
    Posts
    25
    nice! it's working now! thx a ton for the quick fix
    (yes Tree is a class, andsort(incCoords.begin(), incCoords.end(), getLowerY); is actually performed inside a method of Tree)

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The problem is essentially that sort expects a callable expression, which it will just call as sort_helper(left, right). But you are passing a member function. A member function belongs to an instance, so if it would call your function, what instance would it belong to? The compiler does not know, and you have not provided enough context to make the compiler know it.
    So solutions to the problem are:
    - Make it static, eg add static before the function (makes it global to all instances of the class, and hence the compiler does not need to know which instance whose function it is to invoke).
    - Make it free. Then it belongs to no instance, so it is fine.
    - Use a lambda, eg:
    Code:
    std::sort(incCoords.begin(), incCoords.end(), [](const Coordinate& left, const Coordinate& right) { left.y < right.y; });
    (Note: Requires a C++11 compliant compiler.)
    - Define operator < for the coordinate class (see operator overloading).
    Last edited by Elysia; 06-13-2013 at 04:53 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Jun 2013
    Posts
    25
    @Elysia: nice! thanks a ton for this clarification! This definitely helped me to understand the actual issue.


    Btw, stupid question but is there a more elegant way to set the range than the following example shows?
    sort first 5 elements:
    std::sort(incCoords.begin(), incCoords.begin()+5, getLowerY);

  9. #9
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Btw, stupid question but is there a more elegant way to set the range than the following example shows?
    O_o

    Elegant?

    I don't know I'd buy anything in C++ as particularly "elegant" in terms of "beauty".

    Code:
    container_type::const_iterator sOrigin(sContainer.begin());
    container_type::const_iterator sTerminus(sContainer.begin());
    std::advance(sTerminus, 5);
    std::sort(sOrigin, sTerminus, Compare);
    This example though works though with every "STL" compatible container while being optimally efficient which is "elegant" in terms of sophistication.

    Soma

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Btw, lambdas can carry state, so you can also for example do:
    Code:
    // Somewhere inside tree
    std::sort(m_Tree.begin(), m_Tree.end(), [this](const TreeValue& left, const TreeValue& right) { SortHelper(left, right); });
    Here, m_Tree is a member variable in Tree, TreeValue is what values would be stored in the container and SortHelper is a member function inside the tree class.
    Because the lambda stores a copy of the this pointer, it can call member functions. All stl algorithms that needs a "comparator function" will happily accept a lambda.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Jun 2013
    Posts
    25
    thanks a ton!

  12. #12
    Registered User
    Join Date
    Jun 2013
    Posts
    25
    alright so thanks to your help I was also able to obtain my Min value in a similar way:

    Code:
    class Tree{
    private:
    static bool getMinY(const Coordinate &a, const Coordinate &b);
    }
    
    class:
    boolTree::getMinY(const Coordinate &a, constCoordinate &b)
    {
    return a.y < b.y;
    }
    
    Coordinate smallestYCoord=*std::min_element(incCoords.begin(), incCoords.end(), getMinY);
    
    double smallestY = smallestYCoord.y

    This works like a charm, but in fact I don't really need a coord struct but just the double value returned.

    This sounds simple but I don't know how to deal with the return type std::min_element delivers.

    Preferably a double value is returned instead of the coord, so I can make use of it like this:
    Code:
    double smallestY = *std::min_element(incCoords.begin(),incCoords.end(),getMinY);
    Edit: nevermind the second idea

    Is this possible at all? If too much work is involved I will just use the coord struct=) Thanks in advance!
    Last edited by coffee_cups; 06-15-2013 at 03:40 PM.

  13. #13
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Is this possible at all?
    O_o

    The result is an iterator an abstraction of a pointer.

    That's why you were able to dereference to get a `Coordinate'.

    Soma

    Code:
    std::min_element(/**/)->y;

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    >>std::min_element(incCoords.begin(), incCoords.end(), getMinY);
    This should be
    std::min_element(incCoords.begin(), incCoords.end(), &Tree::getMinY);
    Otherwise the code is ill-formed, if getMinY is really a static member function of your Tree.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User
    Join Date
    Jun 2013
    Posts
    25
    thanks a lot guys!! 8)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 06-13-2013, 06:15 PM
  2. Sorting a struct based on an array of ints
    By nair in forum C Programming
    Replies: 3
    Last Post: 10-12-2010, 09:00 AM
  3. Sorting a vector of structs....
    By ropitch in forum C++ Programming
    Replies: 7
    Last Post: 07-10-2009, 11:49 PM
  4. Sorting Vector of structs.
    By Zosden in forum C++ Programming
    Replies: 41
    Last Post: 10-22-2008, 12:28 AM
  5. Sorting Vector of Structs in STL
    By creativeinspira in forum C++ Programming
    Replies: 5
    Last Post: 08-07-2007, 01:54 AM