dav*_*ewy 7 c++ lambda boost c++11
我有一些 C++11 代码,比如
std::vector<std::string> names;
std::map<std::string, std::string> first_to_last_name_map;
std::transform(names.begin(), names.end(), std::inserter(first_to_last_name_map, first_to_last_name_map.begin()), [](const std::string& i){
if (i == "bad")
return std::pair<std::string, std::string>("bad", "bad"); // Don't Want This
else
return std::pair<std::string, std::string>(i.substr(0,5), i.substr(5,5));
});
Run Code Online (Sandbox Code Playgroud)
我使用带有 lambda 函数的 std::transform 将向量转换为地图。我的问题是,有时,如图所示,我不想从我的 lambda 函数返回任何内容,即我基本上想跳过那个i并转到下一个(不向地图添加任何内容)。
有什么方法可以实现我的想法吗?如果有帮助,我可以使用 boost。我想避免一个解决方案,我必须对我的向量进行预处理或后处理以过滤掉“坏”项目;我应该只需要查看每个项目一次。此外,我的实际逻辑比所写的 if/else 更复杂一些,所以我认为如果可能的话,将事情封装在这个 std::transform/lambda 模型中会很好(尽管也许我正在努力实现这个模型是不可能的)。
编辑:只是为了强调,我希望以最有效的方式执行此操作(有选择地处理向量元素并将它们插入到地图中),即使这意味着不太优雅的解决方案或大的重写。我什至可以根据最有效的方式使用不同的地图数据类型。
您只需使用 进行第一次/最后一次传递即可std::remove_if。例如
std::vector<std::string> names;
std::map<std::string, std::string> first_to_last_name_map;
std::transform(names.begin(),
std::remove_if(names.begin(),
names.end(),
[](const std::string &str){
return str=="bad";
}),
std::inserter(first_to_last_name_map,
first_to_last_name_map.begin()),
[](const std::string& i){
return std::pair<std::string, std::string>(i.substr(0,5), i.substr(5,5));
});
Run Code Online (Sandbox Code Playgroud)
请注意,remove_if只是将删除的项目移过它返回的迭代器。
template<class Src, class Sink, class F>
void transform_if(Src&& src, Sink&& sink, F&& f){
for(auto&& x:std::forward<Src>(src))
if(auto&& e=f(decltype(x)(x)))
*sink++ = *decltype(e)(e);
}
Run Code Online (Sandbox Code Playgroud)
现在只需获得增强或标准或标准体验可选。获得您的f退货optional<blah>。
auto sink = std::inserter(first_to_last_name_map, first_to_last_name_map.begin());
using pair_type = decltype(first_to_last_name_map)::value_type;
transform_if(names, sink,
[](const std::string& i)->std::optional<pair_type>{
if (i == "bad")
return {}; // Don't Want This
else
return std::make_pair(i.substr(0,5), i.substr(5,5));
}
);
Run Code Online (Sandbox Code Playgroud)
我个人首选的选项实际上已经定义了开始结束。我们得到这个算法:
template<class Src, class Sink, class F>
void polymap(Src&& src, Sink&& sink, F&& f){
for(auto&& x:std::forward<Src>(src))
for(auto&& e:f(decltype(x)(x)))
*sink++ = decltype(e)(e);
}
Run Code Online (Sandbox Code Playgroud)
现在让f返回一个范围,其中可选的是零或一个元素范围的模型。
| 归档时间: |
|
| 查看次数: |
4854 次 |
| 最近记录: |