2015-12-14 35 views
3

我有一个结构循环通过结构作为关键的地图。

struct key 
{ 
    int x; 
    int y; 
    int z; 
}; 

说的x,y和z可以取的值从1到10

我也有一个地图

std::map<key,double> myMap; 

我与不同的密钥值填充。

有没有一种方法来循环所有的关键值,其中说z = 5。这是(在伪代码方面)

loop over myMap 
    double v += myMap.find({x=anything,y=anything,z=5})->second; 

这将是很亲切,如果有人可以提供一些意见,这是否是可以实现的(我不想使用升压容器)。

回答

5

如果排序key结构使用z先将,你可以这样做:

bool operator<(const key &k1, const key &k2) 
{ 
    return std::make_tuple(k1.z, k1.x, k1.y) < std::make_tuple(k2.z, k2.x, k2.y); // z must be first 
} 

auto min = std::numeric_limits<int>::min(); 
auto end = map.lower_bound( key{ min, min, 6 }); 
for(auto it = map.lower_bound( key{ min, min, 5 }); it != end; ++it) { 
    ... 
} 

,但如果你需要对x或y进行迭代,您将不得不使用指向结构的每个坐标创建单独的多图,或使用boost::multiindex

+0

这很好,但是你最好使用'(5,INT_MIN,INT_MIN)=>(5,INT_MAX,INT_MAX)'或者你的搜索范围。这里的整数已经签名。 – QuestionC

+0

@QuestionC同意,更新的答案,谢谢 – Slava

+1

因为它不执行任何复制,所以首选[std :: tie](http://en.cppreference.com/w/cpp/utility/tuple/tie)用于字典对比。此外,'k1.y'和'k2.y'代替'k1,y'等。好的答案。 – AndyG

5

标准关联容器使用一维排序,即他们只知道一个键是否小于,等于或大于另一个。所以这是不可能的。您可以使用std::find_if()以线性时间实现此类过滤。

维护O(log n)查找时间,但是可以创建多个具有不同索引方式的地图;例如一个与X,一个与Y和一个与Z作为关键。如果值是大对象,则可以使用指针来不必要地重复它们。当然,这些都可以隐藏在封装类的后面,它提供了基于轴的外部排序。

对于小空间(如x,y,z从1到10)合理的另一种方法是不使用std::map,而是使用3D阵列/矩阵。这可以通过使用一维std::vector来实现,通过映射指数从3个维度为1

0
#define ARRAY_SIZE 2500 // 2500 is the size of the array 

为什么不喜欢

double map[2][ARRAY_SIZE]; 
// map[0][x] - the key of Xth value in the array (example - 10th/1st/2nd ...) 
// map[1][x] - the value of Xth value in the array 

只是说创建一个数组的数组,这是更好的,当你不复杂!