使用map / unordered_map(多维)的多个键

时间:2014-03-22 01:45:13

标签: c++ map hashmap

Consier我有一些桶(vector<float>)。我需要根据一些索引访问这个桶。例如:

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

但我觉得这很难看,可悲的是它也非常<强烈>慢。例如,访问1700点,需要0.56秒,这太慢了。

有没有更好/更快的选择,没有使用Boost?
请注意,我需要的这种数据结构可与稀疏矩阵(多维)相媲美,因为很少有&#34;桶和#34;将充满一些东西。

2 个答案:

答案 0 :(得分:3)

您可以使用包含4个索引作为键的unordered_map struct,而使用vector<float>作为值类型,而不是使用这个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;

由于您不想使用Boost,请提出自己的hash_combine替代方案或从here复制实施。

Live example

答案 1 :(得分:2)

只要您不需要访问维度中的所有点(即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;

应用您的示例用例:

BucketMap_t indexedTable;
indexedTable[Point_t(indexX, indexY, indexZ, indexW)].push_back (myValue);