c++11 sorting list using lambda

2019-04-09 08:09发布

问题:

During the study lambda I wanted sort my list by second element(int). This ussed code.

#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 errors:

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?

回答1:

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.



回答2:

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.