【问题标题】:Copy std::map into std::vector of pairs将 std::map 复制到成对的 std::vector 中
【发布时间】:2019-05-20 03:16:35
【问题描述】:

我正在尝试将地图复制到成对的向量中,因此我可以通过成对的 second 数据成员对向量进行排序。我已经解决了这个问题:

void mappedWordsListSorter(){
  for (auto itr = mappedWordsList.begin(); itr != mappedWordsList.end(); ++itr){
    vectorWordsList.push_back(*itr);
  }
  sort(vectorWordsList.begin(), vectorWordsList.end(), [=](pair<string, int>& a, pair<string, int>& b){return a.second > b.second;});
}

我需要找到一种方法来做到这一点,而不使用原始循环,而是使用标准库。我遇到了很多这样的例子,只传输地图的键或值。我需要复制到pairs&lt;string, int&gt; 的向量中。最好的方法是什么?

【问题讨论】:

  • @Lorand - 排序发生在对中的 second 项目上,这不是关键。
  • @Lorand 似乎 OP 希望根据值而不是键来执行排序。
  • 似乎应该将该问题标记为该问题的副本,因为@NathanOliver 提供的答案比该问题的任何答案都要好。编辑:虽然该问题包括对结果进行排序。
  • @ALX23z - 我同意 [=] 不应该出现。但仅仅因为它的存在并不意味着 everything 被复制。 lambda 必须使用来自周围范围的东西来捕获它。
  • @ALX23z 实际上,如果您在 lambda 正文中使用它,它只会复制一个变量。如果您不使用范围内的任何变量,则使用 [=] 不会降低性能。

标签: c++ stdvector stdmap c++-standard-library std-pair


【解决方案1】:

值得注意的是,如果你为此目的创建一个向量,你可以直接使用向量的构造函数:

std::vector<std::pair<FirstType,SecondType>> vectorWordsList( mappedWordsList.begin(), mappedWordsList.end() );

在 C++17 中,您还可以省略向量的模板参数以让编译器推导出它们:

std::vector vectorWordsList( mappedWordsList.begin(), mappedWordsList.end() );

【讨论】:

  • 除非你想创建一个迭代器向量,否则你需要括号。
【解决方案2】:

只需使用std::vector 的assign 成员函数即可。

//no need to call reserve, bidirectional iterators or better will compute the size and reserve internally.
vectorWordsList.assign(mappedWordsList.begin(), mappedWordsList.end());

如果您不想覆盖向量中的现有值,请使用 insert 代替

vectorWordsList.reserve(vectorWordsList.size() + mappedWordsList.size()); // make sure we only have a single memory allocation
vectorWordsList.insert(vectorWordsList.end(), mappedWordsList.begin(), mappedWordsList.end());

【讨论】:

  • 我希望assign 在内部基本上是reserve。
  • @FrançoisAndrieux 如果您传递随机访问迭代器,很可能会这样,但由于 map 具有双向迭代器,它需要遍历才能知道要为多少元素分配空间,所以它不会那样做.
  • @NathanOliver libstdc++ 实际上在内部实际上是 reserve。对于任何 ForwardIterator,它将调用std::distance,为任何小于 RandomAccessIterator 的东西支付遍历费用。你可以追踪std::vector::assign到here。
  • @贾斯汀酷。谢谢你找到那个。我仍然喜欢明确,以防其他实现不这样做。
  • 如果要替换元素,在 .reserve() 之前放置 .resize(0) 可能是一种优化。
【解决方案3】:

您可以使用std::copy 和std::back_inserter:

std::copy(mappedWordsList.begin(), 
          mappedWordsList.end(), 
          std::back_inserter(vectorWordsList));

老实说,我认为 range-for 循环更清晰:

for(const auto& kv : mappedWordsList) 
     vectorWordsList.emplace_back(kv);

无论如何,您都可以使用std::vector::reserve 在目标vector 上预分配内存,避免不必要的重新分配。

【讨论】:

    猜你喜欢
    • 2011-05-19
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    • 2012-01-06
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    相关资源
    最近更新 更多