c – 对于具有相对较旧的编译器的循环与标准库算法

我知道代码在没有任何令人困惑的循环时更好.在可能的情况下重用标准库算法总是好的.但是,我发现迭代器和算法的语法看起来真的很混乱.

我想从我当前的项目中给出一个真实的例子:我想要复制vector< vector< QString>>的内容.进入载体< QVariant>出.我看不出以下区别:

for (int i = 0; i < in[0].size(); i++ ) 
{ 
    if(in[0][i].isNull() || in[0][i].isEmpty() ) 
        out[i] = "NONE";
    else
        out[i] = in[0][i];
}

然后:

std::transform(in[0].begin(), in[0].end(), out.begin(), [](const QString& a)->QVariant{
    if(a.isNull() || a.isEmpty() ) 
        return "NONE";
    else
        return a;
}); 

由于我们有visual studio 2012,我甚至必须输入我的lambda的返回值.使用范围之后:

in[0].map!( a => a.isNull() || a.isEmpty() ? "NONE" : a ).copy(out);

在D语言中,我根本无法使用上面的std :: transform代码.我甚至不确定它是否比基本的循环更好.我的问题是:使用std :: transform的代码是否比for循环好?

最佳答案
至少在我看来,这里的主要问题是变换只是工作的错误工具.

你想要做的就是std :: replace_copy_if所做的事情,所以(没什么大惊喜)它做得更整齐.

我手边的机器上没有安装Qt,所以我冒昧地将你的QVariant和QString代码替换为std :: vector< std :: string>,但我相信同样的基本思想应该适用于Qt类型也是如此.

#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <string>

int main() {   
    std::vector<std::string> input { "one", "two", "", "three" };
    std::vector<std::string> output;

    // copy input to output, replacing the appropriate strings:
    std::replace_copy_if(input.begin(), input.end(),
                         std::back_inserter(output),
                         [](std::string const &s) { return s.empty(); }, 
                         "NONE");

    // and display output to show the results:
    std::copy(output.begin(), output.end(),
              std::ostream_iterator<std::string>(std::cout, "\n"));
}

目前,这只是用NONE替换空字符串,但添加空检查应该是非常简单的(当然,isNull的类型是有意义的).

根据上面的数据,我得到了你可能期望的结果:

one
two
NONE
three

不过,我应该补充一点,即使这显然是非常冗长的.当我们至少将范围添加到标准库时会很好,所以(例如)input.begin(),input.end()可以只用输入替换.结果仍然可能不会像你给出的D代码那样简洁,但至少它会稍微减少冗长(同样适用于大多数其他算法).

如果您关心这一点,您可能需要查看几个范围库 – 一个是Boost Range,(在我看来更有趣)Eric Neibler’s range library.

转载注明原文:c – 对于具有相对较旧的编译器的循环与标准库算法 - 代码日志