2017-04-02 43 views
0

我定义的映射来计算串的数量,同时通过其长度排序字符串:C++地图自定义比较

struct cmp { 
    bool operator()(const string& a, const string& b) { 
     return a.size() > b.size(); 
    } 
}; 

int main() { 
    map<string, int, cmp> mp; 
    mp["aaa"] = 1; 
    mp["bbb"] = 2; 
    cout << mp["aaa"]; 
} 

我很困惑,输出为2。我应该如何实现我的目标是什么?

回答

3

由于比较器的定义方式,字符串“aaa”和“bbb”被认为是相等的。你的地图有一个项目,而不是两个。首先,您将1分配给该项目,然后分配给2

为了解决这个问题,定义比较如下:

struct cmp { 
    bool operator()(const string& a, const string& b) { 
     return a.size() == b.size() ? a > b : a.size() > b.size(); 
    } 
}; 

这样,字符串将被视为平等的,只有当他们实际上是平等的,而不是只有当它们的大小相匹配,但字符串长度仍然有优先排序。

+0

明白了,谢谢! – Seraph

1

std::map不仅按产品按键排序,还按存储按(唯一)键 - 每个键1项。

此行为是由比较器定义:如果钥匙a & b既不a<bb<a是真实的,这些键被认为是相等的。

在你的情况下mp["bbb"] = 2只是覆盖mp["aaa"]

如果您想要适合地图中的所有字符串,可以使用std::multimap,它允许每个键的值超过1。

另一种方法是重新定义比较,以便它会采取不同的字符串到:

struct cmp { 
    bool operator()(const string& a, const string& b) { 
     if(a.size() < b.size()) return true; 
     if(b.size() < a.size()) return false; 
     return a<b; 
    } 
}; 

因此,你的地图仍然将优先通过字符串长度排序,但它也将区分不同的字符串相同的尺寸。

根据您的使用情况,您还可以使用正确的插入技术检查其他容器,如priority_queue或只是普通的vector

+1

非常感谢你的解释!现在更清楚了 – Seraph

0

如果你想允许大小相同的字符串在你的地图,但不关心他们的相对顺序,然后std::multimap是一种替代解决方案:

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

struct cmp { 
    bool operator()(const std::string& a, const std::string& b) const { 
     return a.size() > b.size(); 
    } 
}; 

int main() { 
    std::multimap<std::string, int, cmp> mp; 
    mp.emplace("eee", 5); 
    mp.emplace("aaa", 1); 
    mp.emplace("bbb", 2); 
    mp.emplace("cccc", 3); 
    mp.emplace("dd", 4); 
    auto const elements_of_size_3 = mp.equal_range("aaa"); 
    for (auto iter = elements_of_size_3.first; iter != elements_of_size_3.second; ++iter) 
    { 
     std::cout << iter->first << " -> " << iter->second << '\n'; 
    } 
} 

输出:

eee -> 5 
aaa -> 1 
bbb -> 2 

std::multimap<std::string, int, cmp>的观点,"eee","aaa""bbb"都是完全相等的,std::multimap允许不同的键相等。实际上它们的相对顺序保证了自C++ 11以来的插入顺序。