C++ 对映射/无序映射使用多个键(多维)

C++ 对映射/无序映射使用多个键(多维),c++,map,hashmap,C++,Map,Hashmap,考虑到我有一些桶(vector)。我需要根据一些索引访问这些存储桶。例如: int indexX, indexY, indexZ, indexW; 因此,当一个新点到达时,我需要将该点放入正确的桶中。现在我在做这样的事情: // X Y Z W => Bucket unordered_map<int, unordered_map<int, unord

考虑到我有一些桶(
vector
)。我需要根据一些索引访问这些存储桶。例如:

int indexX, indexY, indexZ, indexW;
因此,当一个新点到达时,我需要将该点放入正确的桶中。现在我在做这样的事情:

//            X                  Y                  Z                  W   => Bucket
unordered_map<int, unordered_map<int, unordered_map<int, unordered_map<int, vector<float>>>>> indexedTable;

// New point arrives and I put it in the right bucket:
indexedTable[indexX][indexY][indexZ][indexW].push_back(myValue);
//X Y Z W=>桶
无序映射可索引;
//新的点到达,我将其放入正确的桶中:
indexedTable[indexX][indexY][indexZ][indexW]。向后推(myValue);
但我觉得这很难看,可悲的是它也很慢。例如,访问1700个点需要0.56秒,这太慢了

在不使用Boost的情况下,是否有更好/更快的替代方案?

请注意,在我的需求中,这个数据结构与稀疏矩阵(多维)相当,因为很少有“bucket”会被某些东西填充。

您可以使用包含4个索引作为键的
无序映射,和
vector
作为值类型。为结构提供一个相等比较器和哈希函数,您就可以开始工作了

struct indices
{
    int indexX, indexY, indexZ, indexW;

    bool operator==(indices const& other) const
    {
        return std::tie(indexX, indexY, indexZ, indexW) ==
               std::tie(other.indexX, other.indexY, other.indexZ, other.indexW);
    }
};

struct indices_hash
{
    std::size_t operator()(indices const& i) const
    {
        std::size_t seed = 0;
        boost::hash_combine(seed, i.indexX);
        boost::hash_combine(seed, i.indexY);
        boost::hash_combine(seed, i.indexZ);
        boost::hash_combine(seed, i.indexW);

        return seed;
    }
};

std::unordered_map<indices, std::vector<float>, indices_hash> m;
struct索引
{
int indexX,indexY,indexZ,indexW;
布尔运算符==(索引常量和其他)常量
{
返回标准::tie(indexX、indexY、indexZ、indexW)==
std::tie(其他.indexX,其他.indexY,其他.indexZ,其他.indexW);
}
};
结构索引\u散列
{
std::size\u t运算符()(索引常量和i)常量
{
std::size\u t seed=0;
boost::hash_combine(种子,i.indexX);
boost::hash_combine(种子,即索引);
boost::hash_combine(种子,i.indexZ);
boost::hash_组合(seed,i.indexW);
返回种子;
}
};
std::无序映射m;
因为您不想使用Boost,所以可以提出自己的
hash\u combine
替代方案,或者从中复制实现


您可以使用一个
无序的
映射,其中
结构包含4个索引作为键,而
向量作为值类型,而不是使用这个4深怪物。为结构提供一个相等比较器和哈希函数,您就可以开始工作了

struct indices
{
    int indexX, indexY, indexZ, indexW;

    bool operator==(indices const& other) const
    {
        return std::tie(indexX, indexY, indexZ, indexW) ==
               std::tie(other.indexX, other.indexY, other.indexZ, other.indexW);
    }
};

struct indices_hash
{
    std::size_t operator()(indices const& i) const
    {
        std::size_t seed = 0;
        boost::hash_combine(seed, i.indexX);
        boost::hash_combine(seed, i.indexY);
        boost::hash_combine(seed, i.indexZ);
        boost::hash_combine(seed, i.indexW);

        return seed;
    }
};

std::unordered_map<indices, std::vector<float>, indices_hash> m;
struct索引
{
int indexX,indexY,indexZ,indexW;
布尔运算符==(索引常量和其他)常量
{
返回标准::tie(indexX、indexY、indexZ、indexW)==
std::tie(其他.indexX,其他.indexY,其他.indexZ,其他.indexW);
}
};
结构索引\u散列
{
std::size\u t运算符()(索引常量和i)常量
{
std::size\u t seed=0;
boost::hash_combine(种子,i.indexX);
boost::hash_combine(种子,即索引);
boost::hash_combine(种子,i.indexZ);
boost::hash_组合(seed,i.indexW);
返回种子;
}
};
std::无序映射m;
因为您不想使用Boost,所以可以提出自己的
hash\u combine
替代方案,或者从中复制实现


< P>只要你不需要访问一个维度内的所有点(即,所有的桶在y=2),那么你应该考虑使用一个结构来表示你的点,而不是嵌套映射。 大致如下:

struct Point_t
{
    int x;
    int y;
    int z;
    int w;
    Point_t (int _x, int _y, int _z, int _w) : x (_x), y (_y), z (_z), w (_w) {}
};

// Make sure the points are sortable
struct CmpPoint_t
{
    bool operator() (const Point_t& lhs, const Point_t& rhs)
    {
        return (lhs.x < rhs.x &&
                lhs.y < rhs.y &&
                lhs.z < rhs.z &&
                lhs.w < rhs.w);
    }
 };

typedef std::vector<float> Bucket_t;
typedef std::map<Point_t, Bucket_t, CmpPoint_t> BucketMap_t;

只要您不需要访问维度内的所有点(即,所有的桶在y=2),那么您应该考虑使用单一结构来表示点,而不是嵌套映射。

大致如下:

struct Point_t
{
    int x;
    int y;
    int z;
    int w;
    Point_t (int _x, int _y, int _z, int _w) : x (_x), y (_y), z (_z), w (_w) {}
};

// Make sure the points are sortable
struct CmpPoint_t
{
    bool operator() (const Point_t& lhs, const Point_t& rhs)
    {
        return (lhs.x < rhs.x &&
                lhs.y < rhs.y &&
                lhs.z < rhs.z &&
                lhs.w < rhs.w);
    }
 };

typedef std::vector<float> Bucket_t;
typedef std::map<Point_t, Bucket_t, CmpPoint_t> BucketMap_t;

我将包含一个包含所有4个参数的
索引的构造函数,并为
std::hash
提供专门化,这样您就不必在
unordered\u映射中显式命名hash
@Praetorian:我将从那里复制hash\u组合,但是hash\u value()函数呢<代码>种子^=**哈希值(v)**+0x9e3779b9+(种子>2)
@llnk只需使用
std::hash{}(v)
即可。我留下了hash_value(),它似乎已经在std::中定义了。我会为
索引包含一个构造函数,该构造函数包含所有4个参数,我将为
std::hash
提供专门化,这样您就不必在
unordered\u map
@Praetorian中显式命名hash:我将从那里复制hash\u组合,但是hash\u value()函数呢<代码>种子^=**哈希值(v)**+0x9e3779b9+(种子>2)
@llnk只需使用
std::hash{}(v)
即可。我留下了hash_value(),似乎它已经在std::非常好的解决方案中定义了。但是为什么我需要这个比较函数呢?如果我使用无序的地图,我不需要对它们进行排序?我相信你只需要==操作符,比如@PretorianIn在一个映射中,必须有一个
操作符非常好的解决方案。但是为什么我需要这个比较函数呢?如果我使用无序的地图,我不需要对它们进行排序?我相信你只需要==操作符,比如@PretorianIn在一个映射中,必须有一个
操作符