转换字符串向量:基于先前的值跳过元素

Transform vector of strings : skip elements based on the previous value

本文关键字:元素 于先前 字符串 向量 转换      更新时间:2023-10-16

我需要将字符串向量转换为小写,但我需要保留文件名的案例。它们由以前的字符串令牌"文件"或" 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"};

在"文件"answers" out"之后保留字符串的情况。

有没有办法使用std::transformlambda函数?

是的。您可以这样使用捕获的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

实时演示

是。您可以捕获一些状态,并根据所见状态进行设置。但是,您不应该使用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;
}

有没有办法使用std :: transform and lambda函数来执行此操作?

std::transform不能保证操作员的固定申请。因此,如果我们需要将std::transform应用于此问题,则最好是二进制操作员的过载:

live demo

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);