Могу ли я получить доступ к элементам в c ++ std :: map по целочисленному индексу? - PullRequest
8 голосов
/ 03 августа 2011

У меня есть карта элементов, которую я хотел бы перебрать. Конечно, стандартный способ сделать это - использовать цикл for с

for (map<string, int> iterator it = myMap.begin(); it != myMap.end(); ++it) {
    string thisKey = it->first;
    int thisValue = it->second;
}

но если я попытаюсь заставить этот цикл работать параллельно, используя параллель OpenMP для конструкции , он не будет работать, и это (по-видимому) известная проблема, так как он не распознает этот конструкция петли.

Итак, мой план резервного копирования состоял в том, чтобы использовать итератор целочисленных индексов и получать доступ к списку ключей и значений по индексу, как я делал бы в C # примерно так:

for (int i = 0; i < myMap.Count; ++i) {
    string thisKey = myMap.Keys[i];
    string thisValue = myMap.Values[i];
}

... пока я не могу найти эквивалентный метод в C ++. Есть ли способ сделать это в C ++, о котором я не знаю?

Ответы [ 2 ]

7 голосов
/ 03 августа 2011

Я ничего не знаю о OpenMP , поэтому я не знаю, оптимизирует ли он следующее или нет. Но вы можете использовать std::advance, вот так:

#include <map>
#include <string>
#include <iterator>
#include <iostream>

typedef std::map<std::string, int> Map;

int main() {
  Map m;
  m["one"] = 1;
  m["two"] = 2;
  for(int i = 0; i < m.size(); ++i) {
    Map::iterator it = m.begin();
    std::advance(it, i);
    std::string thiskey = it->first;
    int thisValue = it->second;
    std::cout << thiskey << "\n";
  }
}

Но учтите, что std::advance - это O (n), поэтому ваша (однопоточная) сложность равна O (n ^ 2).

<час /> EDIT : если вы копируете элементы карты в вектор, то понимаете, что вы можете сделать это в одной декларации:

std::vector<Map::value_type> v(m.begin(), m.end());

следующим образом:

#include <map>
#include <string>
#include <iterator>
#include <iostream>
#include <vector>

typedef std::map<std::string, int> Map;

int main() {
  Map m;
  m["one"] = 1;
  m["two"] = 2;
  int i = 0;
  for( std::vector<Map::value_type> v(m.begin(), m.end());
    i < v.size(); ++i) {
    std::string thiskey = v[i].first;
    int thisValue = v[i].second;
    std::cout << thiskey << "\n";
  }
}
5 голосов
/ 03 августа 2011

Вот несколько вариантов, которые относительно безболезненны.

  1. Сохраните std::vector или std::deque для доступа к массиву и отдельную карту значений. Работа по обеспечению их согласованности - это ваша проблема.

  2. Используйте boost :: multi_index , чтобы обеспечить согласованность между двумя структурами индекса. Как предупреждение, время компиляции довольно длинное с этой опцией. Если вы идете по этому пути, попробуйте использовать идиома pimpl .

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

...