Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++11 sorting list using lambda

While practicing the use of lambdas, I wrote this program which is supposed to sort a list of pairs by their second element (an int).

#include <iostream>
#include <algorithm>
#include <list>

using namespace std;
int main()
{
    list<pair <string, int>> s = {{"two", 2}, {"one", 1}, {"three", 3}};

    sort(s.begin(), s.end(), [](pair<string,int> a, pair<string, int> b) -> bool {
        return (a.second) > (b.second);
    });

    for_each(s.begin(), s.end(), [](pair<string, int> a) {
        cout << a.first << " " << a.second << endl;
    });
}

I get those errors, though:

c:\qt\qt5.2.0\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_algo.h:5513: error: no match for 'operator-' (operand types are 'std::_List_iterator<std::pair<std::basic_string<char>, int> >' and 'std::_List_iterator<std::pair<std::basic_string<char>, int> >')
     std::__lg(__last - __first) * 2, __comp);
                  ^

c:\qt\qt5.2.0\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_algo.h:2245: ошибка: 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::_List_iterator<std::pair<std::basic_string<char>, int> >; _Compare = main()::__lambda0]', declared using local type 'main()::__lambda0', is used but never defined [-fpermissive]
     __final_insertion_sort(_RandomAccessIterator __first,
     ^

What is wrong with my code?

like image 909
punksta Avatar asked Mar 09 '14 12:03

punksta


2 Answers

You may not use std::sort with sequential containers such as std::list or std::forward_list because they have no random access iterator that is required by the standard algorithm std::sort. By this reason the both containers have their own member functions sort.

In you case the code will look the following way:

#include <iostream>
#include <list>
#include <string>

using namespace std;

int main()
{
    list<pair <string, int>> s = {{"two", 2}, {"one", 1}, {"three", 3}};
    s.sort( []( const pair<string,int> &a, const pair<string,int> &b ) { return a.second > b.second; } );

    for ( const auto &p : s )
    {
        cout << p.first << " " << p.second << endl;
    }
}

Take into account that you need to include header <string> otherwise your program will not be compiled with other compilers.

like image 102
Vlad from Moscow Avatar answered Oct 22 '22 02:10

Vlad from Moscow


std::sort requires random access iterators, which std::list does not have. But you can use std::list::sort instead.

s.sort([](const pair<string,int>& a, const pair<string,int>& b)
       {
         return (a.second) > (b.second);
       });

where I have made the parameters of the predicate const references, since there is no need to copy them, and doing so might incur some unnecessary overhead.

like image 33
juanchopanza Avatar answered Oct 22 '22 02:10

juanchopanza