【问题标题】:Can I access the elements in a c++ std::map by an integer index?我可以通过整数索引访问 c++ std::map 中的元素吗?
【发布时间】:2011-10-18 15:33:42
【问题描述】:

我有一张想要遍历的元素地图。当然,这样做的标准方法是使用 for 循环

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

但如果我尝试使用 OpenMP 的 parallel for 构造使这个循环并行运行,它就不起作用,而且这(显然)是一个已知问题,因为它无法识别这种类型循环构造。

所以,我的备份计划是使用整数索引迭代器,并按索引访问键和值的列表,就像我在 C# 中所做的那样:

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

...但我似乎无法在 C++ 中找到等效的方法。有没有办法在我不知道的 C++ 中做到这一点?

【问题讨论】:

  • 您确定std::map 是实现目标的最佳容器吗?
  • 遍历map是遍历树,不是简单的操作。即使您能够以您想要的方式对其进行索引,它也不会为您并行化。
  • 你的这张地图有几对?
  • 马克:谢谢,这几乎回答了我的问题。我认为我当前的解决方案(遍历树并将结果复制到向量中,然后遍历向量)可能是最好的方法。 JK:对于这个特定的应用程序,99991。

标签: c++ dictionary iterator openmp stdmap


【解决方案1】:

我对@9​​87654321@一无所知,所以不知道它是否会优化以下内容。但是你可以使用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)。


编辑:如果您将地图元素复制到矢量,请意识到您可以在一个声明中做到这一点:
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";
  }
}

【讨论】:

  • 我实际上尝试过.. 它非常慢。我几乎失去了通过多线程运行它获得的所有时间,而且我有 24 个线程在运行。我现在的解决方案是声明一个vector和一个vector,调整它们的大小,然后将数据转储到向量中,然后以这种方式访问​​它们。它增加了很少的开销,但它看起来像一个kluge .
  • 保留map::value_type 的单个向量可能会更好。请参阅我的编辑。 (嗯,但这不会 reserve 足够的初始内存。)
【解决方案2】:

这里有一些相对无痛的选项。

  1. 保留 std::vectorstd::deque 用于数组访问,以及单独的值映射。确保它们保持一致的后续工作是您的问题。

  2. 使用boost::multi_index 确保两个索引结构之间的一致性。作为警告,这个选项的编译时间很长。如果你走这条路,考虑使用the pimpl idiom

我没有使用 OpenMP 的经验,因此我无法推测这些选项中的任何一个在实践中是否值得。

【讨论】:

    猜你喜欢
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 2019-01-05
    • 1970-01-01
    • 2011-04-28
    相关资源
    最近更新 更多