在字符串向量中查找字符串不区分大小写的c ++

时间:2016-04-08 08:07:29

标签: c++ string vector find case

我有

std::vector<std::string> vec;
std::string myString; 

我需要使用不区分大小写的comaprisons了解myString是否在vec

我知道我可以使用

find(vec.begin(), vec.end(), myString) != vec.end())

回答问题“vec中是myString吗?”但这将进行区分大小写的比较。我需要不区分大小写的比较。

这个位置并不重要,我只是想知道myString是否在vec中。

6 个答案:

答案 0 :(得分:4)

您需要使用std :: tolower和std :: find_if:

function momentToDate(input) { // Do NOT use the result to anything else than passing it into globalize
    var res = new Date(input.year(), input.month(), input.date(), input.hour(), input.minute(), input.seconds(), input.milliseconds());
    var offset = input.utcOffset();
    res.getTimezoneOffset = function() {
        return offset;
    }
    return res;
}

答案 1 :(得分:3)

您需要使用std::find_if并提供自定义比较器。为了实现不区分大小写的比较,我建议您将要比较的两个字符串转换为常见情况:lower或upper。这将产生如下代码:

auto ret = std::find_if(vec.begin(), vec.end(),
    [&myString](const std::string& s) {
        if (s.size() != myString.size())
            return false;
        return std::equal(s.cbegin(), s.cend(), myString.cbegin(), myString.cend(), [](auto c1, auto c2) { return std::toupper(c1) == std::toupper(c2); });
    });

如果没有找到vec.end(),则返回一个迭代器myString。您可以使用该迭代器做任何事情(包括将其与vec.end()进行比较以了解您是否找到了您的字符串)。

奖励:在Coliru

上运行最少示例

答案 2 :(得分:3)

或者,对于很多更小且更易于阅读的解决方案,Boost!

// #include <algorithm>
// #include <boost/algorithm/string/predicate.hpp>

const auto it = std::find_if(
   std::begin(vec),
   std::end(vec),
   [&myString](const auto& str) { return boost::iequals(myString, str); }
);

const bool found = (it != std::end(vec));

答案 3 :(得分:2)

您可以使用std::find_if,内嵌lambda和std::tolower进行比较:

//Computing the lower version of mystring
std::string my_string_lower;
my_string_lower.reserve(mystring.size());
std::transform(mystring.begin(), mystring.end(), std::back_inserter(my_string_lower), ::tolower);

// Checking if it is exist in the vector:
auto is_exist = std::find_if(vec.begin(), vec.end(), [&my_string_lower](std::string item){
    //Transform the each vector item to lower temporally 
    std::transform(item.begin(), item.end(), item.begin(), ::tolower);
    return mystring==item;
}) != vec.end();

如果您要在字符串的同一个字符中多次搜索,那么如果您计算一次它会更好:

//Computing the lower version of the whole vector
std::vector<std::string> vec_lower;
vec_lower.reserve(vec.size());
std::transform(vec.begin(), vec.end(), std::back_inserter(vec_lower),[](std:string item){
    std::transform(item.begin(), item.end(), item.begin(), ::tolower);
    return item;
});

//Computing the lower version of mystring
std::string my_string_lower;
my_string_lower.reserve(mystring.size());
std::transform(mystring.begin(), mystring.end(), std::back_inserter(my_string_lower), ::tolower);

// Checking if it is exist in the lower version of the vector:
auto is_exist = std::find_if(vec_lower.begin(), vec_lower.end(), [&my_string_lower](const std::string& item){
    return mystring==item;
}) != vec_lower.end();

答案 4 :(得分:1)

template <class T>
long VecFindIgnoreCase( const std::vector< T >& vec, const std::string& sFind ) {
    return VecFindIgnoreCase( vec, sFind.c_str() );
}

template <class T>
long VecFindIgnoreCase( const std::vector< T >& vec, const char* sFind )
{
    for ( std::vector< T >::const_iterator iter = vec.begin(); iter != vec.end(); ++iter )
        if ( _stricmp( (*iter).c_str(), sFind ) == 0 )
            return (long)std::distance( vec.begin(), iter );
    return -1;
}

template <class T>
long VecFindIgnoreCase( const std::vector< T >& vec, const std::wstring& sFind ) {
    return VecFindIgnoreCase( vec, sFind.c_str() );
}

template <class T>
long VecFindIgnoreCase( const std::vector< T >& vec, const wchar_t* sFind )
{
    for ( std::vector< T >::const_iterator iter = vec.begin(); iter != vec.end(); ++iter )
        if ( _wcsicmp( (*iter).c_str(), sFind ) == 0 )
            return (long)std::distance( vec.begin(), iter );
    return -1;
}

使用:

#include <string>
#include <vector>

void TestCode()
{
    std::vector< std::string > strvecA;
    std::vector< std::wstring > strvecW;

    strvecA.push_back("abc");
    strvecA.push_back("def");             
    strvecA.push_back("ghi");
    strvecW.push_back(L"abc");
    strvecW.push_back(L"def");
    strvecW.push_back(L"ghi");

    long ind;

    ind = VecFindIgnoreCase( strvecA, "ABC" ); // ind = 0 found
    ind = VecFindIgnoreCase( strvecA, "ghI" ); // ind = 2 found
    ind = VecFindIgnoreCase( strvecA, "Xyz" ); // ind = -1 not found

    ind = VecFindIgnoreCase( strvecW, L"aBc" ); // ind = 0 found
    ind = VecFindIgnoreCase( strvecW, L"DEF" ); // ind = 1 found
    ind = VecFindIgnoreCase( strvecW, L"xyZ" ); // ind = -1 not found

    std::string sFind( "mno" );
    if ( (ind = VecFindIgnoreCase( strvecA, sFind )) >= 0 ) {
        // found at strvecA[ind]
    } else {
        // not found
    }
}

答案 5 :(得分:0)

由于std::find的性能比std::count好,所以我要实现一个函数模板在std::vector中搜索:

template <class Iterator>
Iterator Find(Iterator first, Iterator last, const char *value)
{
    while (first != last)
    {
        if (StrCmpIA((*first).c_str(), value) == 0)
        {
            return first;
        }

        first++;
    }

    return last;
}

现在你可以像这样使用模板函数:

vector<string> vecStr = {"ali", "reza", "hamid", "saeed"};

if (Find(vecStr.begin(), vecStr.end(), "saeeD") != vecStr.end())
{
    cout << "found" << endl;
}
else
{
    cout << "not found" << endl;
}