Если у меня есть stl-карта из строки в int, и я хочу напечатать все отсортированные значения int - как я могу это сделать?
Как я могу сортировать карту по ее параметру .second
Ответ 1
Вы не можете сортировать карту по ее значениям из-за реализации карты.
Если вы хотите испускать элементы на карте в таком упорядоченном порядке, вы должны сначала выгрузить содержимое карты в вектор (скажем) и отсортировать этот вектор:
template <typename T1, typename T2>
struct less_second {
typedef pair<T1, T2> type;
bool operator ()(type const& a, type const& b) const {
return a.second < b.second;
}
};
map<string, int> mymap;
// …
vector<pair<string, int> > mapcopy(mymap.begin(), mymap.end());
sort(mapcopy.begin(), mapcopy.end(), less_second<string, int>());
Или, наоборот, просто скопируйте значения с карты, оставив ключи и отсортируйте полученный вектор напрямую.
Ответ 2
Вы можете скопировать все значения в вектор и отсортировать его.
#include <algorithm>
#include <map>
#include <vector>
int get_second( pair<string, int> i ){ return i.second; }
int main(int argc, char* argv){
map<string, int> m;
map["tt"] = 2;
map["rr"] = 1;
map["ee"] = 3;
vector<int> v( m.size() );
transform( m.begin(), m.end(), v.begin(), get_second );
sort( v.begin(), v.end() );
for (int i=0; i<v.size(); i++) cout << v[i] << endl;
}
Ответ 3
Вы не можете сделать это автоматически. std::map
использует первое значение (nomen omen 'key') для сортировки содержимого.
Вместо этого вы можете использовать boost::multi_index_container
.
Ответ 4
Если вам нужно сделать это несколько раз, может быть более эффективным сохранить два отдельных контейнера, например. ваша карта и сортированный контейнер, например set
или multiset
для хранения отсортированных целых чисел, вместо того, чтобы создавать контейнер и сортировать его на лету. Но тогда вы должны синхронизировать их, что может привести к ошибкам. Вы можете инкапсулировать это, обернув их в класс или лучше использовать boost::multi_index_container
.
Ответ 5
Вы не можете сортировать карту, ее ассоциативный контейнер, а не последовательный и связанные с ним контейнеры сортируются по некоторому внутреннему порядку.
Если вы хотите только напечатать значения int
, вы можете поместить их в std::vector
, отсортировать вектор и распечатать значения.
Ответ 6
Вместо использования vector
, я скорее всего скопирую их в set<int>
:
#include <map>
#include <set>
#include <string>
#include <iostream>
#include <iterator>
using namespace std;
set<int> map2set(map<string, int> const& m) {
set<int> r;
for (map<string, int>::const_iterator b = m.begin(), e = m.end(); b != e; ++b)
r.insert(b->second);
return r;
}
int main() {
map<string, int> m;
m.insert(make_pair("hello", 42));
m.insert(make_pair("world", 24));
set<int> s = map2set(m);
copy(s.begin(), s.end(), ostream_iterator<int>(cout, "\n"));
}