2013-03-19 2 views
3

Я пытаюсь решить проблему, когда я вставляю символы на карту типа <char, int>. Если char уже существует на карте, я увеличиваю int на 1. Я создал свой собственный компаратор для определения приоритетов элементов на карте. Приоритет не работает так, как я надеюсь, что это сработает, поскольку в конце вывод не соответствует порядку.Карта не сортируется относительно компаратора C++

#include <iostream> 
#include <string> 
#include <map> 
#include <iterator> 

using namespace std; 

struct classcomp { 
    bool operator()(const int& a, const int& b) const { 
     return a < b; 
    } 
}; 

bool isPresent(map<char,int,classcomp> mymap, char c){ 
    return (mymap.find('b') != mymap.end()); 
} 

int main(){ 
    string input="dadbadddddddcabca"; 
    map<char,int,classcomp> mymap; 
    char temp; 

    for(string::iterator it = input.begin(); it!=input.end(); ++it){ 
     temp = *it; 
     if(!isPresent(mymap, temp)) 
      mymap.insert(pair<char,int>(*it,1)); 
     else 
      mymap[temp]++; 
    } 

    for (auto& x: mymap) { 
     cout << x.first << ": " << x.second << '\n'; 
    } 


    return 0; 
} 

дает следующий результат:

a: 4 
b: 2 
c: 2 
d: 8 
+2

Карты сортируются в соответствии с ключом. Ваше сравнение не отличается от сравнения по умолчанию для 'char'. – juanchopanza

+1

Компаратор предназначен для сортировки ключей, а не значений. –

+0

Клавиши выглядят правильно отсортированными: 'a, b, c, d'. –

ответ

2

станд :: Карта предназначена для сортировки по ключу, а также предоставление компаратора для типа значения, ничего не меняет. Представьте, что у вас есть std::map<char,char>, как вы думаете, что вы можете предоставить компаратору значение (если это будет возможно)?
Так решение было бы использовать контейнер, который позволяет сортировать несколькими клавишами, как буст :: multi_index или просто создать еще одну карту - наоборот:

#include <iostream> 
#include <string> 
#include <map> 
#include <iterator> 

using namespace std; 

int main(){ 
    string input="dadbadddddddcabca"; 
    map<char,int> mymap; 

    for(string::iterator it = input.begin(); it!=input.end(); ++it){ 
     mymap[*it]++; 
    } 
    map<int,char> reversemap; 
    for (auto& x: mymap) { 
     reversemap.insert(make_pair(x.second, x.first)); 
    } 

    for (auto& x: reversemap) { 
     cout << x.first << ": " << x.second << '\n'; 
    } 


    return 0; 
} 

Обратите внимание, что ваш предварительно проверить элемент является полностью существования излишними, станд :: map operator [] создает новый элемент и инициализирует его, если он не существует. Вы можете заметить, что на выходе у вас отсутствуют некоторые значения (хотя они отсортированы), если это не то, что вам нужно, измените тип карты обратной связи с карты на мультимап, что позволяет дублировать ключи.

+0

"обратная карта [x.second] = x.first;" это не очень хорошая идея, потому что некоторые «секунды» могут быть равными – borisbn

+0

@borisbn спасибо, исправлено. – Slava

+0

hmmm ... не вижу ... AFAIK 'reverseemap [x.second] = x.first;' равно 'reverseemap.insert (make_pair (x.second, x.first));' – borisbn

1

map сортирует записи по ключу, а не значение. Клавиши char бесшумно отбрасываются до int в вашем classcomp::operator()

0

Карты сортируются по их клавишам.

Ваш пользовательский компаратор classcomp применит к ключам не значение.

2

Компаратор используется для сортировки char с, а не для int.

Он сортирует ключи и работает нормально - a b c d.

+0

Компаратор ** может ** сравнивать' ints', пока контейнер содержит («масло маслянистое», как мы, - говорят россияне))) 'chars' – borisbn

+0

Я хотел взять свой нисходящий, но SO сказать, что я не могу, если вы не отредактируете свой ответ. Пожалуйста, внесите в него какие-либо изменения. – borisbn

+0

@borisbn - Спасибо. Я переместил свой комментарий на ответ. –

1

Почему

mymap.find('b') != mymap.end()); 

и не

mymap.find(c) != mymap.end()); 
0

Может быть, это то, что вы хотели

int main() { 
    std::string input="dadbadddddddcabca"; 
    typedef std::map< char, int > map_t; 
    map_t mymap; 
    char temp; 

    for (std::string::const_iterator it = input.begin(), e = input.end(); it != e; ++it) { 
     temp = *it; 
     mymap[ temp ] = mymap[ temp ] + 1; // Hopufuly operator[] inserts zero initialized value, if can't find a key 
    } 
    typedef std::pair< typename map_t::key_type, typename map_t::mapped_type > pair_t; 
    std::vector<pair_t> sortedByValue; 
    sortedByValue.assign(mymap.begin(), mymap.end()); 
    std::sort(sortedByValue.begin(), sortedByValue.end(), [](const pair_t & left, const pair_t & right) { 
     return left.second < right.second; 
     // change to 
     // return left.second > right.second; 
     // for descend order 
    }); 

    for (const auto & x: sortedByValue) { 
     std::cout << x.first << ": " << x.second << std::endl; 
    }  
} 

LWS link

Смежные вопросы