C++ 给定从键到索引的映射,将值(映射的_类型)从映射复制到向量

C++ 给定从键到索引的映射,将值(映射的_类型)从映射复制到向量,c++,algorithm,c++11,stl,c++14,C++,Algorithm,C++11,Stl,C++14,假设我们有一个函数key\u to\u index,它将映射的键映射到向量的索引。举个例子,让我们把它简单化: std::map<int, int> source = {{1,55}, {4, 20}, {6, 25}}; std::vector<int> target; int key_to_index(int key) {return key;} 基本上,您可以创建一个新的映射,该映射使用转换的键存储相同的值: std::map<int, int> t

假设我们有一个函数
key\u to\u index
,它将映射的键映射到向量的索引。举个例子,让我们把它简单化:

std::map<int, int> source = {{1,55}, {4, 20}, {6, 25}};
std::vector<int> target;

int key_to_index(int key) {return key;}

基本上,您可以创建一个新的映射,该映射使用转换的键存储相同的值:

std::map<int, int> transformed;

std::transform(std::cbegin(source), std::cend(source),
        std::inserter(transformed, transformed.end()),
        [](const auto& e) {
            return std::make_pair(key_to_index(e.first), e.second);
        }
);
std::map转换;
std::transform(std::cbegin(源代码),std::cend(源代码),
插入器(已转换,已转换.end()),
[](const auto&e){
返回std::make_pair(键到索引(e.first),e.second);
}
);
然后填充目标:

std::vector<int> target;
target.resize(transformed.rbegin()->first + 1);

std::for_each(std::cbegin(transformed), std::cend(transformed),
        [&target](const auto& e) {
            target[e.first] = e.second;
        }
);
std::向量目标;
target.resize(transformed.rbegin()->first+1);
std::for_each(std::cbegin(转换)、std::cend(转换),
[&目标](常数自动和e){
目标[e.first]=e.second;
}
);


无论如何,我相信最初的版本更好。STL并不总是使代码更高效,甚至更可读。

基本上,您可以创建一个新的映射,用转换的键存储相同的值:

std::map<int, int> transformed;

std::transform(std::cbegin(source), std::cend(source),
        std::inserter(transformed, transformed.end()),
        [](const auto& e) {
            return std::make_pair(key_to_index(e.first), e.second);
        }
);
std::map转换;
std::transform(std::cbegin(源代码),std::cend(源代码),
插入器(已转换,已转换.end()),
[](const auto&e){
返回std::make_pair(键到索引(e.first),e.second);
}
);
然后填充目标:

std::vector<int> target;
target.resize(transformed.rbegin()->first + 1);

std::for_each(std::cbegin(transformed), std::cend(transformed),
        [&target](const auto& e) {
            target[e.first] = e.second;
        }
);
std::向量目标;
target.resize(transformed.rbegin()->first+1);
std::for_each(std::cbegin(转换)、std::cend(转换),
[&目标](常数自动和e){
目标[e.first]=e.second;
}
);


无论如何,我相信最初的版本更好。STL并不总是使代码更高效,甚至更可读。

@Edgar的答案很好,但是,我不喜欢第二次创建地图。假设
key\u to\u index
相当快,最好只运行两次,而不是使用转换后的索引创建map

对代码的明显优化(除非
键到索引
太复杂)是避免多次调整大小。然后对原始地图应用
std::for_each

auto max = std::max_element(source.cbegin(), source.cend(), [](auto& lhs, auto& rhs) {
    return key_to_index(lhs.first) < key_to_index(rhs.first); });
target.resize(key_to_index(max->first) + 1);

std::for_each(source.cbegin(), source.cend(), [&target](const auto& e) {
    target[key_to_index(e.first)] = e.second; });
auto max=std::max\u元素(source.cbegin(),source.cend(),[](auto&lhs,auto&rhs){
返回键到索引(lhs.first)<键到索引(rhs.first);};
调整大小(键到索引(max->first)+1);
std::for_each(source.cbegin()、source.cend()、[&目标](const auto&e){
目标[key-to-index(e.first)]=e.second;});

@Edgar的答案很好,但是,我不喜欢第二次创建地图。假设
key\u to\u index
相当快,最好只运行两次,而不是使用转换后的索引创建map

对代码的明显优化(除非
键到索引
太复杂)是避免多次调整大小。然后对原始地图应用
std::for_each

auto max = std::max_element(source.cbegin(), source.cend(), [](auto& lhs, auto& rhs) {
    return key_to_index(lhs.first) < key_to_index(rhs.first); });
target.resize(key_to_index(max->first) + 1);

std::for_each(source.cbegin(), source.cend(), [&target](const auto& e) {
    target[key_to_index(e.first)] = e.second; });
auto max=std::max\u元素(source.cbegin(),source.cend(),[](auto&lhs,auto&rhs){
返回键到索引(lhs.first)<键到索引(rhs.first);};
调整大小(键到索引(max->first)+1);
std::for_each(source.cbegin()、source.cend()、[&目标](const auto&e){
目标[key-to-index(e.first)]=e.second;});


您可以创建一个输出迭代器,非常类似于
std::insert_迭代器
,其值类型为
std::pair
操作符=
,可以改变数组。然后,您的函数可以写成
std::transform
您可以创建一个输出迭代器,非常类似于
std::insert_迭代器
,其值类型为
std::pair
操作符=
,可以改变数组。那么你的函数可以写成
std::transform

你的
键到索引()
函数真的应该返回
键而不是
索引吗?@Galik OP说他把它做成了一个微不足道的身份函数,是为了减少注意力。实际实现应该无关紧要。您可以将它包装成
std::transform
并使用lambda,但除此之外,我想说的是保持原样。@DeiDei您能证明一下吗?是您的
键到索引()
函数真的应该返回
键,而不是
索引
?@Galik OP确实说过,为了降低注意力,他将其设置为微不足道的身份函数。实际的实现应该无关紧要。您可以将它包装成
std::transform
并使用lambda,但除此之外,我会说保持原样。@DeiDei您能证明一下吗?我希望它会比原始代码短。。。而且我绝对不希望使用STL的版本比原始版本效率更低。@AlwaysLearning有时最好避免使用STL:)@EdgarRokyan亵渎神明的评论!竖起大拇指!我希望它会比原来的代码短。。。而且我绝对不希望使用STL的版本比原始版本效率更低。@AlwaysLearning有时最好避免使用STL:)@EdgarRokyan亵渎神明的评论!竖起大拇指!“我不喜欢第二次创建地图”。是的,我也不喜欢。刚刚发布了我脑海中浮现的第一个版本。总之,+1:)不错!这看起来确实比原始版本快。它还避免了循环中的条件“我不喜欢第二次创建贴图”。是的,我也不喜欢。刚刚发布了我脑海中浮现的第一个版本。总之,+1:)不错!这看起来确实比原始版本快。它还避免了循环内部的条件。好主意,尽管我不会那么努力地重新编写四行代码。好主意,尽管我不会那么努力地重新编写四行代码。