为什么在std :: map中有排序机制?

时间:2019-05-25 21:49:49

标签: c++ visual-c++ stl

我想使用std::map作为键/值对,并且要保持插入这些键/值对的顺序。 当我打印我的值时,顺序以某种方式重新排列。下面是我的代码

string removeDuplicates(string& s)
{
    // string& s = "asdasdasd"
    map<char, int> duplicates;
    for (int i = 0; i < s.length(); i++) {
        duplicates[s[i]]++;
    }
    map<char, int>::iterator itr = duplicates.begin();
    string result;
    while (itr != duplicates.end())
    {
        result += itr->first;
        itr++;
    }
    return result;
}

我插入了"asdasd",我希望有"asd",但结果是"ads"

2 个答案:

答案 0 :(得分:1)

这是一个功能,而不是错误。 std::map就是这样设计的-遍历地图所基于的红黑树总是按照地图键的顺序进行。

您可能很想尝试std::unordered_map,但不会获得想要的结果。这将按照您可能称为“随机”的顺序进行入侵。

如果要保留出现在字符串中的字符的原始顺序,则必须自己执行。但是您可以这样做并同时构建结果字符串:

string removeDuplicatesKeepingOriginalOrder(string const& s)
{
    // string& s = "asdasdasd"
    string result;
    std::map<char, int> index;
    auto si = s.begin();
    auto se =s.end();
    while (si!=se)
    {
       auto f = index.find (*si);
       if (f==index.end())
       {
          ++index[*si];
          result.push_back(*si);
          ++si;
       }
    }
    return result;
}

答案 1 :(得分:0)

经过Spencer更新的答案后,我认为我们完全不需要映射,只要我们的目标只是从字符串中删除重复项。这是我只有std :: string

的解决方案
string removeDuplicatesKeepingOriginalOrder(string const& s)
{
    string result;
    for(std::size_t i=0;i<s.size();i++)
    {
        if(result.find(s[i]) == std::string::npos)
        {
            result.push_back(s[i]);
        }
    }
    return result;
}