Std::transform with lambda:跳过一些项
std::transform with lambda: skip some items
我有一些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));
});
,其中我使用std::transform与lambda函数转换向量到映射。我的问题是,有时,如图所示,我不想从我的lambda函数返回任何东西,即我基本上想跳过那个i
,去下一个(不添加任何到映射)。
有没有办法达到我想要的?如果有用的话,我可以用boost。我希望避免必须对向量进行预处理或后处理以过滤掉"坏"项的解决方案;每个项目我只需要看一次。此外,我的实际逻辑比所写的if/else要复杂一些,所以我认为如果可能的话,最好把东西封装在这个std::transform/lambda模型中(尽管我想要实现的可能是这个模型不可能实现的)。
编辑:只是为了强调,我希望以最有效的方式执行此操作(有选择性地处理向量元素并将它们插入到映射中),即使这意味着不那么优雅的解决方案或大量重写。我甚至可以根据最有效的方式使用不同的地图数据类型。
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);
}
现在简单地得到一个boost或std或std实验可选。让你的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));
}
);
我个人的首选选项实际上已经定义了begin end。我们得到这个算法:
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);
}
现在允许f
返回一个范围,其中可选的是零或一个元素范围的模型。
您可以简单地使用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));
});
注意,remove_if
只是将移除的项移到它返回的迭代器后面。
您可以使用boost::adaptors::filtered
先过滤不需要的vector
元素,然后再将其传递给transform
。
using boost::adaptors::filtered;
boost::transform(names | filtered([](std::string const& s) { return s != "bad"; }),
std::inserter(first_to_last_name_map, first_to_last_name_map.begin()),
[](std::string const& i) { return std::make_pair(i.substr(0,5), i.substr(5,5)); });
现场演示
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 可组合的lambda/std::函数与std::可选
- 使用std::transform将一个范围的元素添加到另一个范围中
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 如何将lambda作为模板类的成员函数参数
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- 在 lambda 捕获中声明的变量的类型推导
- 我可以将调用类的"this"传递给 lambda 函数吗?
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 模板函数指针和lambda
- 两组使用lambda函数的大括号
- 使lambda不可复制/不可移动
- FLTK:按下哪个按钮 - 将数字传递给按钮的回调 (lambda)
- 尝试将lambda函数放在队列中时出现一般分配器错误(可能是与unique_ptr有关的错误)
- 在 lambda(parameter) 中为 std::transform with std::sregex_token
- 如何使用for_each,transform,Iterator和lambda的某种组合将STD ::集合的字符串转换为小
- 为什么在 std::transform 中使用函数对象参数失败并且需要 lambda 表达式
- Std::transform with lambda:跳过一些项
- c++的transform和lambda函数