【问题标题】:Using std::transform to convert a std::vector<struct{key; val;}> into a std::map<key, val>使用 std::transform 转换 std::vector<struct{key; val;}> 到 std::map<key, val>
【发布时间】:2018-04-07 11:10:22
【问题描述】:

鉴于这些类型:

struct ComplexLibraryThing { /*lots of fields*/};
typedef std::map<int, ComplexLibraryThing> MyMap;
struct ShadowComplexLibraryThing { /*Shadow of ComplexLibraryThing*/};
struct MyVecType { int a; ShadowComplexLibraryThing b; };
typedef std::vector<MyVecType> MyVector;

我可以为序列化执行此操作(我的序列化库不支持类似地图的类型):

MyVecType map2pair(std::pair<int, ComplexLibraryThing> const &myPair)
{
    MyVecType retVal;
    retVal.a = myPair.first;
    retVal.b = convertForSerialisation(myPair.second);
    return retVal;
}

MyMap myMap = {...};
MyVector myVector;
std::transform(myMap.begin(),
               myMap.end(),
               std::back_inserter(myVector),
               map2pair);

然后我将向量发送给想要重建MyMap 的接收器。但是,我找不到像这样进行反序列化的合适的&lt;algorithm&gt; 模板:

MyMap myNewMap;
for (auto const &entry: myVector)
    myNewMap[entry.a] = convertForDeserialisation(entry.b);

我将如何使用&lt;algorithm&gt; 编写此内容?

(注意图中的ComplexLibraryThing类型不能轻易更改,但我也有一个ShadowComplexLibraryThing可以)

【问题讨论】:

  • 你能修改MyVecType吗?如,添加成员函数?
  • 你为什么不在另一端做同样的事情:std::transform 有一个函数?或者将std::for_each() 与 lambda 结合起来?我想我错过了一些东西:-/
  • @piwi 我不确定用什么替换std::back_inserter...
  • 您的修改没有回答我的问题。你能修改MyVecType本身吗?
  • 顺便说一句,您有什么理由要使用算法吗?基于范围的 for 循环让我觉得比转换简单得多。 (特别是如果您将正文更改为myNewMap.insert(std::make_pair(entry.a, convertForDeserialisation(entry.b));(这避免了默认构造映射条目然后分配给它。)。

标签: c++ c++11 stl stl-algorithm


【解决方案1】:

这篇文章展示了如何为 std::map 创建插入器:

How to insert into std::map?‌​p

被迭代的事物的类型必须是std::pair&lt;KeyType, EntryType&gt;(所谓的value_type of std::map)。

我觉得是这样的:

std::pair<int, ComplexLibraryThing> vec2pair(const MyVecType &myVec)
{
    return std::make_pair(myVec.a,
                          transformForDeserialization(myVec.b));
}

MyVector myVector = {...};
MyMap myMap;
std::transform(myVector.begin(),
               myVector.end(),
               std::inserter(myMap, myMap.end()),
               vec2pair);

【讨论】:

  • 我认为make_pair 必须是std::make_pair(myVec.a, transformForDeserialization(myVec.b))
  • 领先我两分钟,但我的想法完全正确!
【解决方案2】:

我认为缺少的关键“技巧”是std::inserter。这是一个小演示。

#include <algorithm>
#include <iterator>
#include <map>
#include <vector>

struct foo {int a; int b;};

std::vector<foo> GenerateSource() {
  return {};
} 

std::pair<int, int> ConvertFooToMapPair(const foo& f) {
    return {f.a, f.b};
}

int main(int argc, char* argv[]) {
  std::map<int, int> destination;
  std::vector<foo> source = GenerateSource();
  std::transform(
    source.begin(), source.end(),
    std::inserter(destination, destination.end()),
    ConvertFooToMapPair);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-25
    • 2016-02-04
    • 2020-07-03
    • 1970-01-01
    • 2017-08-13
    • 1970-01-01
    • 2014-02-13
    相关资源
    最近更新 更多