2015-12-14 2 views
3

У меня есть структураЦитирование через карту со структурой как ключом.

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

скажем х, у, г может принимать значения от 1 до 10.

У меня также есть карта

std::map<key,double> myMap; 

который я заселить с различными значениями ключа ,

Есть ли способ перебрать все ключевые значения, где say z = 5. То есть (в терминах псевдокода)

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

Было бы очень любезен, если кто-то может дать некоторые комментарии относительно того, является ли это достижимо (я не хочу использовать подталкивание контейнеры).

ответ

5

При сортировке key структура с помощью г первых, вы можете сделать это следующим образом:

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-матрице. Это может быть реализовано с использованием 1D 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 

Просто сказать, что лучше, когда вы не затруднит!

Смежные вопросы