Kad*_*mir 4 c++ algorithm c++11
我知道当代码中没有任何令人困惑的for循环时,代码会更好.在可能的情况下重用标准库算法总是好的.但是,我发现迭代器和算法的语法看起来真的很混乱.
我想从我当前的项目中给出一个真实的例子:我想将内容复制vector<vector<QString>> in到vector<QVariant> out.我看不出以下区别:
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];
}
Run Code Online (Sandbox Code Playgroud)
然后:
std::transform(in[0].begin(), in[0].end(), out.begin(), [](const QString& a)->QVariant{
if(a.isNull() || a.isEmpty() )
return "NONE";
else
return a;
});
Run Code Online (Sandbox Code Playgroud)
由于我们有visual studio 2012,我甚至必须输入我的lambda的返回值.使用范围之后:
in[0].map!( a => a.isNull() || a.isEmpty() ? "NONE" : a ).copy(out);
Run Code Online (Sandbox Code Playgroud)
在D语言中,我根本无法忍受std::transform上面的代码.我甚至不确定它是否比基本for循环更好.我的问题是:使用std::transform上面的代码比for循环好吗?
至少在我看来,这里的主要问题是,这transform只是工作的错误工具.
你要做的就是做什么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"));
}
Run Code Online (Sandbox Code Playgroud)
目前,这只是替换空字符串NONE,但添加空检查应该是非常简单的(isNull当然,有一种类型是有意义的).
根据上面的数据,我得到了你可能期望的结果:
one
two
NONE
three
Run Code Online (Sandbox Code Playgroud)
不过,我应该补充一点,即使这显然是非常冗长的.当我们至少将范围添加到标准库时,这将是很好的,所以(例如)input.begin(), input.end()可以用just替换input.结果仍然可能不会像你给出的D代码那样简洁,但至少它会稍微减少冗长(同样适用于大多数其他算法).
如果您关心这一点,那么range您可能需要查看几个库 - 一个Boost Range,以及(在我看来更有趣)Eric Neibler的范围库.