【问题标题】:passing iterators to lambda [closed]将迭代器传递给 lambda [关闭]
【发布时间】:2017-07-05 07:17:24
【问题描述】:

我想对以下代码使用 lambda 表达式,

long long noOfways =0;
 auto dist =0;
 for(auto iter = noChocolets.begin()+1;iter!=noChocolets.end();iter++)
 {   
     dist+=*(iter)-*(iter-1);
     noOfways+=  minOper(dist);
 }

我特别想将 for 循环 转换为 lambda 表达式。我怎样才能做到这一点?

【问题讨论】:

  • 为什么要使用 lambda?
  • 你为什么要改变一个工作代码,(我认为)不需要重构?
  • @Ansu - 这是一个 XY 问题。你有一个问题 X,你问你想到的(错误)解决方案,Y。所以直接问 X。
  • @Ansu 顺便说一句,你有一个潜在的错误潜伏在for 循环中......如果noChocolets 怎么办?那么noChocolets.begin() + 1未定义的!
  • @Someprogrammerdude - 前进到基于 for 的范围当然需要一些重组。然而,并非不可能。

标签: c++ c++11 lambda iterator


【解决方案1】:

尝试使用 std::accumulate。

 accumulate(noChocolets.begin()+1, noChocolets.end(), noChocolets[0],
    [&](long long left, long long right){
        dist += right-left;
        noOfways += minOper(dist);
        return right;
    });

似乎可行,尽管这是一个奇怪且晦涩的解决方案。如果你问我,原来的更干净。我认为这是对累积方法的滥用,不建议使用它。

Working example

【讨论】:

  • “滥用累积” - 我不同意。积累差异并没有滥用。命名算法使我在循环中更清楚。 +1
  • 我的意思是累加的意思是返回累加的结果。这个只返回最后一个元素。这样一来,这个解决方案对我来说就晦涩难懂了。
  • 如果没有丢弃该值,我会同意你的看法。该算法可能比此处所需的更通用,但这仍然是一个不错的解决方案,否则您将无法说服我:)
【解决方案2】:

您可以抽象它以防万一您需要在同一块

中重用它
auto f = [](auto& itercollection)
{
    for(auto iter = itercollection.begin()+1;iter!=itercollection.end();iter++)
    {   
        dist+=*(iter)-*(iter-1);
        noOfways+=  minOper(dist);
    } 
}

然后就调用它:

f(noChocolets)
f(noChocolets2)
f(noChocolets3)

【讨论】:

  • 我想把for循环换成lambda,可以吗?
  • @Ansu,如果你需要迭代你必须迭代,lambdas 只是匿名函数。
  • 老实说,在基于范围的 for 而没有 lambda 上建议 for_each 很奇怪
  • @StoryTeller,现在你说,是的,它不正确,我要编辑,谢谢。
【解决方案3】:

迭代器的使用等同于基于范围的循环/lambda 和std::for_each,因此总有一种方法可以将其中一种方法替换为另一种方法。但正如 cmets 中提到的,迭代器方法具有其清晰性的优势......示例性 c++17 解决方案:

#include <vector>
#include <algorithm>
#include <optional>

int main() {
    std::vector<int> v {1, 2, 3, 4};
    auto dist =0;
    long long noOfways =0;
    auto minOper = [](auto e) {return e;};
    std::optional<decltype(v)::value_type> prev {};
    std::for_each(v.begin(), v.end(), [&](auto e)  { 
        if (prev.has_value()) {
            dist += e - prev.value();
            noOfways+=  minOper(dist);
        }
        prev = e;
    });
}

[live demo]

要将其反向移植到 c++11,请使用 boost::optional and non-generic lambdas

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 2013-06-03
    • 2014-06-26
    • 2013-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多