2010-03-16 10 views
18

Jeśli mam mapę stl od ciągu do int i chcę wydrukować wszystkie wartości int posortowane - jak mogę to zrobić?Jak mogę posortować mapę według jej parametru .second

+0

@Danh Aktualny konsensus jest zamknięcie przez "jakość": Ponieważ "jakość" nie jest mierzalna, po prostu przechodzę przez upvotes. ;-) Prawdopodobnie sprowadza się to do tego, które pytanie trafiło w najlepsze słowa kluczowe newb Google dotyczące tytułu. –

+0

@Danh: W ogólnym przypadku jest to prawdą - w przypadku 'map ', nie jest koniecznie prawdą, że istnieją porównania nawet dla 'value_type' . Dla konkretnego przypadku 'mapy ' możliwe jest porównanie według wartości. –

Odpowiedz

24

Nie można posortować mapy według jej wartości ze względu na implementację mapy.

Jeśli chcesz emitować elementy w mapie w taki posortowanych potem trzeba najpierw zrzucić zawartość map do wektora (powiedzmy) i sortowania, który Vector:

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>()); 

lub alternatywnie, tylko skopiuj wartości z mapy, pozostawiając klawisze i bezpośrednio sortuj wynikowy wektor.

+0

Po wstawieniu do wektora zarówno "pierwszego", jak i drugiego "drugiego", dlaczego nie wstawić go do 'std :: map ? – sbi

+0

@sbi: oczywiście, ponieważ byłoby to * waaay * zbyt proste i oczywiste. :-P –

+3

@sbi, wartości mogą się powtarzać. –

1

Nie można sortować mapy, jest to kontener skojarzony , a nie sekwencyjny, a powiązane kontenery są sortowane według kolejności wewnętrznej.

Jeśli chcesz wydrukować tylko wartości int, możesz ustawić je w postaci std::vector, posortować wektor i wydrukować wartości.

+0

Myślę, że chce wydrukować wszystkie ciągi posortowane według ich ints :) –

+0

'std :: map's nie są sortowane według" niektórych "kolejności .. Są sortowane według jawnie podanych wartości kluczowych, w tym przypadku ciągów. –

+0

@malleor: Tak, wiem. I 'std :: unordered_map' jest sortowane według innej kolejności. Napisałem o _associated containers_, a nie o 'std :: map' w tej frazie. – sbi

3

Jeśli chcesz zrobić to wiele razy, lepiej będzie przechowywać dwa oddzielne pojemniki, np. Twoja mapa i posortowany pojemnik, taki jak set lub multiset do przechowywania posortowanych int, zamiast konieczności tworzenia pojemnika i sortowania go w locie. Ale potem musisz je zsynchronizować, co może stać się brudne. Można to zawrzeć, zawijając je w klasę lub jeszcze lepiej, używając boost::multi_index_container.

0

Zamiast korzystać z vector, wolałbym po prostu skopiować je do 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")); 
} 
5

Można skopiować wszystkie wartości w wektorze i sortować je.

#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; 
    m["tt"] = 2; 
    m["rr"] = 1; 
    m["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; 
} 
Powiązane problemy