2015-12-14 34 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 

只是說創建一個數組的數組,這是更好的,當你不復雜!