C++ C++;转换地图<;int,set<;int>&燃气轮机;进入地图<;int,向量<;int>&燃气轮机;

C++ C++;转换地图<;int,set<;int>&燃气轮机;进入地图<;int,向量<;int>&燃气轮机;,c++,map,vector,set,move,C++,Map,Vector,Set,Move,我必须像这样转换std::map: std::map<int, std::set<int> > t_contents; std::map<int, std::vector<int> > seq; std::映射t_内容; 在这样的地图中: std::map<int, std::set<int> > t_contents; std::map<int, std::vector<int> > seq

我必须像这样转换std::map:

std::map<int, std::set<int> > t_contents;
std::map<int, std::vector<int> > seq;
std::映射t_内容;
在这样的地图中:

std::map<int, std::set<int> > t_contents;
std::map<int, std::vector<int> > seq;
std::map seq;
我以这种方式进行转换:

std::map<int, std::set<int> >::const_iterator it;
for(it = t_contents.begin(); it != t_contents.end(); ++it)
{    
    std::move((*it).second.begin(), (*it).second.end(), 
        std::back_inserter(seq[(*it).first])
    );   
}
std::map::const_迭代器it;
for(it=t_contents.begin();it!=t_contents.end();++it)
{    
std::move((*it).second.begin(),(*it.second.end(),
标准:背面插入器(顺序[(*it).first])
);   
}

考虑到地图包含多达100万个元素,每个集合也可以包含多达10000个元素。这是我在浪费空间和时间方面找到的最佳解决方案;有没有更好的方法来完成这项工作?

如果使用暗示插入,性能会更好(每次插入的摊销常数):

std::map<int, std::set<int> >::const_iterator it;
for (it = t_contents.begin(); it != t_contents.end(); ++it) {
    std::vector<int> &vec = seq.insert(seq.end(),
        std::make_pair(it->first, std::vector<int>()))->second;
    vec.reserve(it->second.size());
    vec.assign(it->second.begin(), it->second.end());
}
注意,不需要移动设置的元素;因为它们是原语,所以移动和复制是一样的

这可能更快或更慢,例如取决于
insert
是否检查迭代器参数之间的距离(在任何情况下,设置的大小都是O(n)。

另一个选项是:

std::transform(t_contents.begin(), t_contents.end(), std::inserter(seq.begin()),
  [](const std::pair<const int, std::set<int>>& s) {
    std::vector<int> v;
    v.reserve(s.second.size());
    v.assign(s.second.begin(), s.second.end());
    return std::make_pair(s.first, std::move(v));
  }
);
std::transform(t_contents.begin()、t_contents.end()、std::inserter(seq.begin()), [](const std::pair&s){ std::向量v; v、 保留(s.second.size()); v、 赋值(s.second.begin(),s.second.end()); 返回std::make_pair(s.first,std::move(v)); } ); 移动
int
s是毫无意义的,而且
std::set
迭代器无论如何都是常量,所以不能移出集合


与ecatmur的回答一样,这得益于插入提示,因为对
insert\u迭代器
的每个赋值都会执行一个
insert
,并将上一个插入点作为提示,这是一个巨大的性能优势,因为输入范围已经按照相同的顺序排序,因此,每个连续的插入都与最后一个相邻。

我认为只有当元素要一个接一个地向后推时,才应该
reserve
,使用
assign
时,可以安全地忽略它。这类似于使用开始和结束迭代器调用ctor。我最初认为保留是不必要的,但实际上
reserve(s.size())
比让
assign
通过使用
std::distance
遍历范围来计算元素要快。赋值可以使用
std::make\u move\u迭代器(it->second.begin())
和类似的
end
来移动元素,就像原始代码一样question@legends2k构造函数被专门记录为检查迭代器之间的距离
assign
(和
insert
)不是,尽管实现很可能会在相同的情况下进行检查。啊,除了移动之外,仍然不会做任何事情,正如
set::iterator
不是可变迭代器所说的那样(尽管太懒了,无法参考标准)在C++11中,插入应该发生在提示之前,而不是之后,在这种情况下,您应该始终将
seq.end()
作为提示传递(至少在C++11中是这样)。顺便说一句,
(*it)。
it->
相同。不幸的是,他说(虽然太懒了,无法参考标准)在C++11中,插入应该发生在提示之前而不是之后,因此使用
seq.begin()
不是一个好主意。但不幸的是,如果每次插入后插入迭代器总是增加提示,那么
seq.end()
将无法工作。@ChristianRau,当我调用
seq.begin()
时,映射是空的,所以
seq.begin()==seq.end()
那么你建议使用什么其他值<代码>插入\迭代器不会增加提示,它会被设置到插入位置,停止懒惰并检查标准;)还有,看,是的,对。24.5.2.6.2[insert.iter.op=]表示“效果:
iter=container->insert(iter,value);++iter;
”。事实上,我错过了
iter=
部分,认为它只是增加了初始提示,这将导致
seq.begin()
的对数插入,而
seq.end()的对数插入失败。事实上,CPPPreference完全符合标准,但我只是没有正确阅读(因此我相当愚蠢而不是懒惰;)。