【问题标题】:STL algorithm to process first N elements which comply with conditionSTL算法处理前N个符合条件的元素
【发布时间】:2019-11-01 11:20:55
【问题描述】:

我有一段代码遍历坐标向量。然后我想使用符合条件的向量中的前 N ​​个坐标。 方法(简化):

Matrix image;
int maxCount = N;
std::vector<Point> coordinates(sizeof >> maxCount);
std::vector<SomeClass> filtered;
filtered.reserve(maxCount);
for (const auto& coordinate : coordinates)
    {
        if (image.at(coordinate) != 255)
        {
            continue;
        }

        filtered.emplace_back(coordinate, ...);

        // end when we have enought points
        if (filtered.size() == maxCount)
        {
            break;
        }
    }

我想要的是避免 for 循环并使用 STL 库。大致是这样的:

for_each_n_if(begin(v), N, [&](Point p){ 
 if(cond) {
      otherVec.emplace_back(p,...);
      return true; // help counter is incremented
 } else {return false;}});

在 stl 中是否有任何功能可以做到这一点? (我确实检查过,只是想知道我是否遗漏了一些不太明显的东西)

【问题讨论】:

  • 为什么?循环不可读吗?
  • 尽可能地尝试使用 stl。我认为可能有一些功能可以处理这种特殊情况。
  • range-v3(很快在C++20):auto res = coordinates | ranges::view::filter([&amp;](const auto&amp; coordinate){ return image.at(coordinate) == 255; }) | ranges::view::take(maxCount);

标签: c++ stl c++17


【解决方案1】:

大多数 STL 算法都专注于一个特定的任务,它们的组合并不好 - 这就是我们首先要获得范围的原因。在那之前,你要么必须

  1. 将您的意图拆分为多个算法调用,
  2. 为您的用例编写特定算法
  3. 继续使用手动循环(毕竟它们可读性很强)或
  4. 使用一个可用的范围库。

2.的一个建议,具体算法:

template <class InputIt, class Size, class OutputIt, class Pred, class Fct>
auto transform_n_if(InputIt first, InputIt last, Size count, OutputIt dest,
    Pred pred, Fct transform)
{
   Size n(0);

   while (first != last && n !=count) {
      if (pred(*first)) {
         *dest++ = transform(*first);
         ++n;
      }

      ++first;
   }

   return dest;
}

可以这样调用:

std::vector<Point> coordinates(someSize);
std::vector<SomeClass> filtered;

transform_n_if(coordinates.cbegin(), coordinates.cend(), 42, std::back_inserter(filtered),
      [](const Point& p){ return /* your condition here... */ true; },
      [](const Point& p){ return /* your transformation here... */ SomeClass(p); });

【讨论】:

  • 这会考虑count 输入,而不是在count 输出之后停止
  • @Caleth:很容易修复,仅当谓词为真时才增加n。 (完成)
【解决方案2】:

当你想停止时,你可以使用std::all_of并从谓词中返回false

std::all_of(coordinates.begin(), coordinates.end(),
            [&](const auto& coordinate)
            {
               if (image.at(coordinate) == 255)
                  filtered.emplace_back(coordinate, ...);
               return filtered.size() < maxCount;
            });

只是我不确定这是否比循环更具可读性。

【讨论】:

  • 我倾向于认为谓词是纯函数,所以这对我来说不太可读。 [&amp;] 是一个快速的赠品,虽然这并不纯粹。
  • @MSalters:如果允许编译器在后台使用并行策略,甚至不确定它是否有效。
  • @Jarod42 不带执行策略参数的std::all_of 版本需要输入迭代器。
  • 那么不能调度随机迭代器吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
相关资源
最近更新 更多