我需要将字符串向量转换为小写字母,但我需要保留文件名的 case 。它们由以前的字符串标记“ file”或“ out”标识。
#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
template <class T>
void print(const T& v) {
std::copy(v.begin(), v.end(),
std::ostream_iterator<typename T::value_type>(std::cout, "\n"));
}
std::string lowercase(const std::string& s)
{
std::string result(s);
std::transform(result.begin(), result.end(), result.begin(), ::tolower);
return result;
}
int main() {
std::vector<std::string> tokens {"Col1", "Col2", "File", "FileIn.dat", "Out", "FileOut.dat"};
std::transform(tokens.begin(), tokens.end(), tokens.begin(), lowercase);
// how to replace lowercase() with a lambda that will take the previous
// element into account while converting an element into lowercase
print(tokens);
return 0;
}
在上面的代码中结果应该是
{"col1", "col2", "file", "FileIn.dat", "out", "FileOut.dat"};
保留“ file”和“ out”之后的字符串的大小写。
是否可以使用std::transform
和lambda
函数来做到这一点?
答案 0 :(得分:2)
是的。您可以像这样使用捕获的lambda:
bool is_filename = false;
std::transform(tokens.begin(), tokens.end(), tokens.begin(),
[&is_filename] (auto &s) {
if (is_filename)
is_filename = false;
else
{
s = lowercase (s);
is_filename = s == "file" || s == "out";
}
return s;
});
输出:
col1
col2
file
FileIn.dat
out
FileOut.dat
答案 1 :(得分:2)
是的。您可以捕获一些状态,然后根据看到的内容进行设置。但是,您不应使用std::transform
,因为它不能保证按顺序遍历。您必须使用std::for_each
。
int main() {
std::vector<std::string> tokens {"Col1", "Col2", "File", "FileIn.dat", "Out", "FileOut.dat"};
bool toggle = true;
auto lowercase = [&toggle](std::string & s)
{
if (toggle)
{
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
}
toggle = (s == "file") || (s == "out");
}
std::for_each(tokens.begin(), tokens.end(), tokens.begin(), lowercase);
print(tokens);
return 0;
}
答案 2 :(得分:1)
是否可以使用std :: transform和lambda函数来做到这一点?
std::transform
不保证按顺序应用操作员。
因此,如果我们需要对这个问题应用std::transform
,则最好使用二进制运算符的重载:
std::vector<std::string> tokens {"Col1", "Col2", "File", "FileIn.dat", "Out", "FileOut.dat"};
{
// The first element must not be file name.
tokens[0] = lowercase(tokens[0]);
std::vector<std::string> dummy;
std::transform(
std::next(tokens.begin()), tokens.end(), tokens.begin(),
std::back_inserter(dummy),
[](auto& target, const auto& prev)
{
const auto prevLower = lowercase(prev);
const auto isFileName = (prevLower == "file") || (prevLower == "out");
if(!isFileName){
target = lowercase(target);
}
return "";
});
}
print(tokens);