在阅读了大多数maps
个问题之后,我最终从这个链接中得到了一个想法:How to unique my data that are stored in an object which are stored in a vector?
我的任务是从用户输入中存储X
,Y
,Z
坐标。为了防止用户输入重复数据,我决定使用地图容器,因为它们不允许重复数据。
我测试了代码。
我使用X
作为key
而Y作为value
我可以通过以下方式存储X
和Y
:
map<int, int> mapp2d;
mapp2d.insert(pair<int, int>(X, Y));
通过以下方式访问它们:
map<int, int>::iterator p = mapp2d.begin();
map<int, int>::iterator e = mapp2d.end();
while ( p != mapp2d.end())
{
cout << "X: " << p->first << " Y: " << p->second << endl;
p++;
}
是否可以为X
,Y
,Z
执行此操作?像这样:
map<int, int, int> mapp3d
mapp3d.insert(pair<int, int, int>(X, Y, Z))
我测试了代码,但是我遇到了这个错误:
error: wrong number of template arguments (3, should be 2)
error: provided for ‘template<class _T1, class _T2> struct std::pair
是的,我确实知道这样做对我来说是违法的,但是我没有关于如何这样做的教程,我有点想法,我怎么能访问它们?
感谢你们一起来看看,先谢谢。
答案 0 :(得分:4)
您应该将坐标存储在一起,而不是将一个坐标用作关键字:
struct Point
{
int x, y, z;
Point(int x, int y, int z) : x(x), y(y), z(z) {}
};
然后只需实现一个自定义比较器:
struct PointComparator
{
bool operator()(const Point& a, const Point& b)
{
if (a.x < b.x) return true;
if (a.x == b.x && a.y < b.y) return true;
if (a.x == b.x && a.y == b.y && a.z < b.z) return true;
return false;
}
};
最后,使用set而不是地图(因为在您的情况下,值和键是相同的):
#include <set>
std::set<Point, PointComparator> points;
默认情况下,从低值到高值设置(就像地图一样)。您需要在此处指定自定义比较器,因为如果您执行std::set<Point>
,则使用的默认比较器为std::less
。这个比较器可以比较数字等,但不知道如何比较Point
类型的对象。因此,该集合可能无法正确排序其元素,也无法确定两个元素是否相同(这就是您所追求的)。如果您执行std::set<Point, PointComparator>
,则会创建一个使用PointComparator
中的逻辑来比较其元素的集合。
此示例将打印“1”和“2”:
points.insert(Point(1, 2, 3));
points.insert(Point(1, 2, 3));
points.insert(Point(2, 3, 4));
std::set<Point, PointComparator>::iterator it = points.begin();
while (it != points.end()) {
std::cout << "x = " << it->x << std::endl;
it++;
}
答案 1 :(得分:1)
你考虑过使用元组吗?它们可用于容纳2个以上的元素
http://www.cplusplus.com/reference/tuple/tuple/
我想如果你真的已经开始使用地图,那么另一种可能性就是做下面的链接,你的地图的值是:
答案 2 :(得分:0)
我不是C ++专家,但我认为你应该使用set而不是map,并使用元组作为值。集合通常用于保存唯一值(虽然我说的是Java和Python知识,而不是C ++)。看看set和unordered_set;显然unordered_set更快,但是set已经排序。他们都没有跟踪你放入的顺序,也没有映射,所以如果你需要,那么你需要找到一个不同的解决方案。我认为元组可以存储任意数量的元素。
答案 3 :(得分:0)
区分存储数据的方式和访问方式通常很有用。
例如,您可以将点存储在矢量中,但可以放置一个唯一性指数&#39;通过使用std :: set来使用它们。这里有一些展示这个想法的独立代码:
#include <functional>
#include <iostream>
#include <memory>
#include <set>
#include <vector>
class Point {
public:
Point(int x, int y, int z) : m_x(x), m_y(y), m_z(z) {}
int x() const { return m_x; }
int y() const { return m_y; }
int z() const { return m_z; }
private:
int m_x;
int m_y;
int m_z;
};
bool operator<(const Point & a, const Point & b) {
return (a.x() < b.x()
|| (a.x() == b.x()
&& (a.y() < b.y()
|| (a.y() == b.y()
&& a.z() < b.z()))));
}
class Points {
public:
Points() {}
bool add(Point p) {
if (m_uniqueIndex.count(p) == 0) {
m_points.emplace_back(new Point(p));
m_uniqueIndex.emplace(*m_points.back());
return true;
}
return false;
}
private:
std::set<std::reference_wrapper<Point>> m_uniqueIndex;
std::vector<std::unique_ptr<Point>> m_points;
};
const char * s(bool b) {
return b ? "true" : "false";
}
int main(int argc, char * argv[]) {
Point a(1, 2, 3);
Point b(2, 1, 0);
Point c(-1, 0, 1);
Point a2(1, 2, 3);
Points points;
std::cout << "Adding a: " << s(points.add(a)) << std::endl;
std::cout << "Adding b: " << s(points.add(b)) << std::endl;
std::cout << "Adding c: " << s(points.add(c)) << std::endl;
std::cout << "Adding a2: " << s(points.add(a2)) << std::endl;
}
根据我的经验,当使用空间数据时,你总是想要提出这样的问题:这个邻居是什么?在这个坐标的某个距离内有多少东西等等。所以我还建议您在k-d trees(对于点)和r trees(对于形状)进行一些阅读。< / p>