Anyway, to store the key, value, value in the map

After reading most of the questions maps

, I got an idea from this link: How unique is my data that is stored in an object that is stored in a vector?

I have the task of keeping the coordinates X

, Y

, Z

with user input. To prevent the user from entering duplicate data, I chose to use map containers as they do not allow duplicate data.

I checked the code.

I use X

like key

and Y likevalue

I can store X

and Y

with this:

map<int, int> mapp2d;
mapp2d.insert(pair<int, int>(X, Y));

      

And to access them through this:

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++; 
}

      

I make it possible for X

, Y

, Z

? Like this:

map<int, int, int> mapp3d
mapp3d.insert(pair<int, int, int>(X, Y, Z))

      

I checked the code, but I got the following errors:

error: wrong number of template arguments (3, should be 2)
error: provided for โ€˜template<class _T1, class _T2> struct std::pair

      

Yes, I know it is illegal for me, but there are no tutorials on how I should do this and I was running out of ideas and how can I access them?

Thank you guys for stopping by, thanks in advance.

+3


source to share


4 answers


You have to store coordinates together instead of one coordinate as keys:

struct Point
{
    int x, y, z;

    Point(int x, int y, int z) : x(x), y(y), z(z) {}
};

      

Then just do a custom comparator:

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;
    }
};

      

And finally, use set instead of map (because in your case the values โ€‹โ€‹and keys are the same):



#include <set>
std::set<Point, PointComparator> points;

      


Sets (as is the case with maps) sorted default values โ€‹โ€‹from low to high. Here you need to specify a custom comparator, because the default is the one that is used only if you do std::set<Point>

, std::less

. This comparator can compare numbers, etc., but has no idea how to compare type objects Point

. So the set couldn't properly order the elements, nor could it determine if the two elements are the same (which is after you). If you do std::set<Point, PointComparator>

, you create a set that uses logic in PointComparator

to compare its elements.

This example will print "1" and "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++;
}

      

+4


source


Have you considered using a tuple? They can be used to store more than 2 items.

http://www.cplusplus.com/reference/tuple/tuple/



I guess another possibility, if you really have your heart set on using the map, is doing something like the link below where your map values โ€‹โ€‹are:

Using Map Search <pair, int>

+1


source


I'm not a C ++ expert, but I think you should be using a set, not a map, and use a tuple for the values. Sets are usually used to store unique values โ€‹โ€‹(although I'm speaking from Java and Python knowledge, not C ++). Have a look at set and unordered_set; obviously unordered_set is faster, but the set is sorted. None of them keep track of the order in which you put things in, and the map doesn't show up either, so if you need that, you'll need to find another solution. And I think tuples can store an arbitrary number of items.

0


source


It is often helpful to distinguish between how you store data and how you access it.

For example, you can store points in a vector, but put a "unique index" on them using, say, std :: set. Here is some standalone code to demonstrate the idea:

#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;
}

      

In my experience, when using spatial data, you always have the right to ask questions such as: what are these neighbors cudinates? How many things are at some distance from this coordinate, etc. So I also recommend that you read a little about kd trees (for points) and r trees (for shapes).

0


source







All Articles