现代过滤STL容器的方法
Modern way to filter STL container?
经过多年的C#我想知道什么现代 - 读:C 11-过滤数组的方式,即我们如何实现与此类似的东西LINQ查询:
var filteredElements = elements.Where(elm => elm.filterProperty == true);
为了过滤一个元素的向量(为了这个问题,strings
)?
我真诚地希望旧的STL样式算法(甚至是boost::filter_iterator
这样的扩展),现在需要定义明确方法现在被取代了吗?
请参阅cplusplus.com的示例 std::copy_if
:
std::vector<int> foo = {25,15,5,-5,-15};
std::vector<int> bar;
// copy only positive numbers:
std::copy_if (foo.begin(), foo.end(), std::back_inserter(bar), [](int i){return i>=0;} );
std::copy_if
在此处评估foo
中每个元素的lambda表达式,如果返回true
,则将值复制到bar
。
std::back_inserter
允许我们在bar
(使用push_back()
)的末尾实际插入新元素,而无需首先将其调整到所需的大小。
在C 20中,使用范围库中的过滤器视图:(需要#include <ranges>
)
// namespace views = std::ranges::views;
vec | views::filter([](int a){ return a % 2 == 0; })
懒惰地返回vec
中的均匀元素。
(请参阅[range.Adaptor.Object]/4和[range.filter])
这已经得到了GCC 10(实时演示)的支持。对于clang和旧版本的GCC,也可以使用#include <range/v3/view/filter.hpp>
(或#include <range/v3/all.hpp>
)和ranges::views
名称空间而不是std::ranges::views
(Live Demo)。
如果您实际上不需要列表的新副本,则是remove_if
,它实际上删除了原始容器中的元素。
我认为Boost.Range
也值得一提。结果代码非常接近原始代码:
#include <boost/range/adaptors.hpp>
// ...
using boost::adaptors::filtered;
auto filteredElements = elements | filtered([](decltype(elements)::value_type const& elm)
{ return elm.filterProperty == true; });
唯一的缺点是必须明确声明lambda的参数类型。我使用了dectType(elements):: value_type,因为它避免了必须拼出确切的类型,并且还增加了一定的通用性。另外,使用C 14的多态性lambdas,可以简单地将类型指定为自动:
auto filteredElements = elements | filtered([](auto const& elm)
{ return elm.filterProperty == true; });
过滤的元素将是一个适合遍历的范围,但基本上是原始容器的视图。如果您需要的另一个容器填充了满足标准的元素的副本(以便它独立于原始容器的寿命),则看起来像:
using std::back_inserter; using boost::copy; using boost::adaptors::filtered;
decltype(elements) filteredElements;
copy(elements | filtered([](decltype(elements)::value_type const& elm)
{ return elm.filterProperty == true; }), back_inserter(filteredElements));
改进的pjm代码下划线d建议:
template <typename Cont, typename Pred>
Cont filter(const Cont &container, Pred predicate) {
Cont result;
std::copy_if(container.begin(), container.end(), std::back_inserter(result), predicate);
return result;
}
用法:
std::vector<int> myVec = {1,4,7,8,9,0};
auto filteredVec = filter(myVec, [](int a) { return a > 5; });
我对C 等效的建议
var filteredElements = elements.Where(elm => elm.filterProperty == true);
定义一个模板函数,您将lambda谓词传递给进行过滤。模板函数返回过滤结果。例如:
template<typename T>
vector<T> select_T(const vector<T>& inVec, function<bool(const T&)> predicate)
{
vector<T> result;
copy_if(inVec.begin(), inVec.end(), back_inserter(result), predicate);
return result;
}
使用 - 给出一个琐碎的示例:
std::vector<int> mVec = {1,4,7,8,9,0};
// filter out values > 5
auto gtFive = select_T<int>(mVec, [](auto a) {return (a > 5); });
// or > target
int target = 5;
auto gt = select_T<int>(mVec, [target](auto a) {return (a > target); });
- "operator()"在重载运算符方法中是什么意思,在priority_queue(STL)中用作C++中的比较器?
- C++ STL 容器中优先级搜索的优雅方法
- 有没有一种 STL 方法可以找到字符串的所有排列,给出一个以 C++ 为单位的大小?
- STL vector.insert 方法期望_InputIterator作为参数
- 是否有任何常规方法可以通知 STL 移动和复制构造函数?
- 遍历 STL 映射(集/多集)的最佳方法,同时元素可能会在循环期间被删除并重新插入?
- 仅编写 c++ stl 向量的第一个元素的正确方法
- 为 STL 随机数生成器编写工厂方法
- 哪些更好的方法可以显示使用C STL创建的堆栈而不弹出每个元素的方法
- 如果其他人在等待,是否有标准的STL或QT方法可以产生互惠码,否则请保留它
- 有没有一种 stl 方法来执行指针向量的深度复制
- 寻找一种更有效的方法来使用 STL 函数检查字符串是否为回文
- 方法插入到任何stl集合中
- STL 中的排序方法不能交换向量中的内容
- 有没有一种方法可以防止在STL无序映射上插入或擦除
- Eclipse CDT无法在STL容器中的元素上解析方法
- 现代过滤STL容器的方法
- 无论CRT版本如何,这都是在库中提供STL函数的有效方法吗
- STL表示隐含交叉引用的数据结构的方法
- 最有可能使用的方法是处理多个键以使用STL容器获取值