ключи не уникальны в c ++ map

У меня есть 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;
}

}

Как вы можете видеть, карта, которую я имею здесь, на самом деле является ассоциацией поплавка и вектора связанных поплавков. Если ключ уже существует, значение добавляется в вектор, соответствующий этому ключу. Но, как я уже сказал, ключи не хранятся однозначно. Кто-нибудь может помочь мне решить эту проблему?

Ракеш.

2

Решение

Проблема с поплавками в том, что вы не можете просто использовать == оператор, чтобы убедиться, что они равны. Например, один номер может быть 7.0 но другой может быть на самом деле 7.000000000015хотя это должно было быть 7.0 также.

Нужно определить точность, с которой вы хотите сравнить эти числа с плавающей запятой и проверить, меньше ли их разность, чем точность. Для данного примера, если мы выберем точность 0.000001эти 2 числа равны, потому что | (7.000000000015 - 7.0)| < 0.000001.

Вы можете реализовать такую ​​логику с помощью собственного компаратора. std::map имеет класс компаратора в качестве одного из аргументов шаблона.

Обновить:

Оказалось, что на самом деле нет общего способа решения проблемы с ключами с плавающей запятой на карте. Проблема, изложенная в комментарии, очень серьезна. Компаратор карт должен гарантировать строгое слабое упорядочение вставляемых ключей, однако это не представляется возможным в общем случае для чисел с плавающей запятой.

Предположим, вы вставляете 3 клавиши: a, b и c. Возможно, что a < b ложно (потому что они равны с заданной точностью), b < c ложно (по той же причине, что и a < b), но вполне возможно, что a и c могут быть настолько «далеки» друг от друга, что a < c вернет true (они не равны), что, что плохо.

Чтобы преодолеть это, вы должны иметь некоторые знания об ожидаемых ключах. Если они достаточно удалены друг от друга (расстояние больше обычной арифметической ошибки с плавающей запятой), можно написать соответствующий компаратор.

Для примера компаратора вы можете обратиться к https://stackoverflow.com/a/6684830/276274

9

Другие решения

Карта не может содержать дубликаты ключей. Вы, наверное, думаете, что это из-за точности с плавающей точкой появиться быть равными на самом деле разные. Чтобы обойти это, вы можете использовать пользовательский Compare Класс с вашей картой, чтобы рассматривать достаточно близкие поплавки как равные:

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

Как насчет хранения 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);
}
0
По вопросам рекламы [email protected]