我们可以得到一个迭代器,该迭代器从C ++中的谓词中过滤出一个向量吗?

时间:2019-06-10 16:37:21

标签: c++ filter iterator stdvector

是否有可能在向量上获得一个迭代器,该谓词用谓词过滤某些元素,即显示向量的视图?

我认为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是执行查询的好方法,但是我不需要复制所有内容,并且最终可能花费太多(不确定这一点),我应该提到的要比数据要多就我而言是一成不变的。

2 个答案:

答案 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是已在谓词上过滤并随后应用了一个函子的数字范围。

请参见compiler-explorer

信用: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,它将成为一个非常昂贵的解决方案。 。