是否有可能在向量上获得一个迭代器,该谓词用谓词过滤某些元素,即显示向量的视图?
我认为remove_if
的功能类似,但是我还没有找到是否可以按自己的意愿使用它。
类似的东西:
auto it = filter(vec.begin(), vec.end(), predicate);
// I can reuse the iterator like:
for (auto i = it; i != vec.end(); i++)
// ...
编辑: (需要更多上下文信息才能获得最佳答案)我正在用日志数据的sqlite数据库进行大量查询,以便打印报告
由于需要的请求数量过多,目前的表现不佳。我相信查询一次数据库并将结果存储在智能指针向量中(如果可能的话,则为unique_ptr
),然后使用纯C ++查询向量可能会更快。
使用copy_if
是执行查询的好方法,但是我不需要复制所有内容,并且最终可能花费太多(不确定这一点),我应该提到的要比数据要多就我而言是一成不变的。
答案 0 :(得分:2)
正如@ Jarod42在评论中提到的,一种解决方案是使用范围:
#include <algorithm>
#include <iostream>
#include <vector>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/transform.hpp>
int main()
{
std::vector<int> numbers = { 1, 2, 3 ,4, 5 };
auto predicate = [](int& n){ return n % 2 == 0; };
auto evenNumbers = numbers | ranges::view::filter(predicate);
auto result = numbers | ranges::view::filter(predicate)
| ranges::view::transform([](int n) { return n * 2; });
for (int n : evenNumbers)
{
std::cout << n << ' ';
}
std::cout << '\n';
for (int n : result)
{
std::cout << n << ' ';
}
}
evenNumbers
是一个范围视图适配器,它坚持numbers
范围并更改其迭代方式。
result
是已在谓词上过滤并随后应用了一个函子的数字范围。
信用:fluentcpp
答案 1 :(得分:1)
您的问题
在要求您使用我们可以得到一个迭代器来从C ++谓词中过滤出一个向量吗?
的意义上,只能用以下方式回答:否。目前还不能(C ++ 17)。根据您的要求,迭代器将必须存储谓词,并检查位置的每次修改或所有取消引用的东西。也就是说,在取消任何引用之前,需要对谓词进行检查。因为其他代码可以修改您的std :: vector。迭代器将需要一直检查谓词。此外,像开始,结束,距离之类的标准功能也相当复杂。
因此,您可以通过派生现有的迭代器来创建自己的迭代器。存储谓词并重载大多数函数以维护谓词。非常非常复杂,需要做很多工作,也许没有,您想要拥有什么。这将是准确获得所需功能的唯一方法。
对于变通办法,还有许多其他可能的解决方案。 Peolple将在这里显示您。
但是,如果我阅读了您的声明
“显示矢量视图”
然后,生活变得更加轻松。您可以按照遗忘的说明,通过使用std :: copy_if有条件地复制来轻松创建矢量视图。我认为这是最好的答案。它没有破坏性。但这是快照,而不是原始数据。因此,它是只读的。而且,它不考虑拍摄快照后对原始std :: vector的更改。
第二个选项是std :: remove_if和std :: erase的组合,将破坏原始数据。或更确切地说,它将使过滤出的数据无效。您也可以将有害数据std :: copy_if备份到备份区域,如果有害数据std :: remove_if进行备份,最后将它们再次添加到向量中。
如果要修改原始数据,所有这些方法都是至关重要的。
也许对您来说,标准的std :: copy_if最好创建一个视图。然后,您将返回copy的迭代器并使用它。
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> testVector{ 1,2,3,4,5,6,7 }; // Test data
std::vector<int> testVectorView{}; // The view
// Create predicate
auto predForEvenNumbers = [](const int& i) -> bool { return (i % 2 == 0); };
// And filter. Take a snapshot
std::copy_if(testVector.begin(), testVector.end(), std::back_inserter(testVectorView), predForEvenNumbers);
// Show example result
std::vector<int>::iterator iter = testVectorView.begin();
std::cout << *iter << '\n';
return 0;
}
请注意。对于大的std :: vectors,它将成为一个非常昂贵的解决方案。 。