【问题标题】:keys not unique in c++ map键在 C++ 映射中不是唯一的
【发布时间】:2012-10-17 09:17:15
【问题描述】:

我的程序中有一个存储成对值的 std::map。我希望地图中的键是唯一的——这是 std::map 类的预期行为。但是当我将这些对插入其中时,会重复一些键。我该如何解决这个问题?

我的代码如下:

map<float,vector<float> *> inpDataMap;
inpDataMap.clear();
    for(int i = 0; i < input.getNum(); i++)
    {

        float xVal = input[i][0];
        float yVal = input[i][1];

        if(inpDataMap.count(xVal) > 0)
        {
            myfile << i << " repeated xval: " << xVal << " : " << yVal << endl;
            inpDataMap[xVal]->push_back(yVal);
            myfile << "repeated value pushed" << endl;
        }
        else
        {
            vector<float> *inVec = new vector<float>;
            inVec->push_back(yVal);
            inpDataMap[xVal] = inVec;
            myfile << i << " not repeated:" << xVal << ":" << yVal << endl;
        }

    }

如您所见,我这里的地图实际上是一个浮点数和相关浮点数向量的关联。如果已经存在一个键,则将该值添加到与该键对应的向量中。但就像我说的,密钥不是唯一存储的。谁能帮我解决这个问题?

拉克什。

【问题讨论】:

  • 你怎么知道键不是唯一的?
  • 这是不真实的,该地图包含重复的键。请举例。
  • 这是标准行为。您有责任确保不向std::map 添加重复条目,如果您需要重复的键条目,请使用std::multimap
  • 问题不在于地图,而在于您的输入。地图可以很好地存储唯一键。
  • 根据定义,键在 std::map 中是唯一的。你自己说这个。然后你说实际上它们并不是唯一的。恐怕你的问题对我来说毫无意义。

标签: c++ map c++-standard-library


【解决方案1】:

浮点数的问题在于您不能简单地使用== 运算符来确保它们相等。例如,一个数字可能是7.0,但另一个实际上可能是7.000000000015,即使它也应该是7.0

要走的路是定义一个精度,你想用它来比较这些浮点数,并检查它们的差是否小于精度。对于给定的示例,如果我们选择 0.000001 的精度,这两个数字相等,因为 | (7.000000000015 - 7.0)| &lt; 0.000001.

您可以通过自己的比较器来实现这种逻辑。 std::map 有一个比较器类作为其模板参数之一。

更新:

事实证明,确实没有解决地图中浮点键问题的通用方法。评论中概述的问题非常严重。映射比较器需要保证插入的键的严格弱排序,但是对于浮点数的一般情况似乎不可行。

假设您要插入 3 个键:a、b 和 c。 a &lt; b 可能是假的(因为它们在给定的精度下是相等的),b &lt; c 是假的(与a &lt; b 的原因相同),但是 a 和 c 可能离“很远”彼此,a &lt; c 将返回 true(它们不相等),这很糟糕。

要克服这一点,您需要对预期的键有所了解。如果它们之间的距离足够远(距离大于通常的浮点算术误差),则可以编写适当的比较器。

如需比较器的示例,您可以转至https://stackoverflow.com/a/6684830/276274

【讨论】:

  • 您的比较器是否遵循严格的弱排序?
【解决方案2】:

地图不能包含重复的键。您可能认为这是因为浮点精度 - 某些对您看似相等的值实际上是不同的。要解决这个问题,您可以在地图中使用自定义 Compare 类来将足够接近的浮点数视为相等:

map<float,vector<float> *, CustomCompare> inpDataMap;

【讨论】:

  • 如果您这样做,您需要非常小心,以便您的自定义比较正确实现严格的弱比较。如果您将“足够接近”的值视为相等,则很容易出错......
【解决方案3】:

如何存储std::vector 而不是指向vector 的指针:

map<float,vector<float> > inpDataMap;
inpDataMap.clear();
for(int i = 0; i < input.getNum(); i++)
{
    float xVal = input[i][0];
    float yVal = input[i][1];
    inpDataMap[xVal].push_back(yVal);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 2014-10-30
    • 2018-03-07
    • 1970-01-01
    • 2013-12-11
    • 1970-01-01
    • 2015-12-27
    相关资源
    最近更新 更多