如何使用STL对字符串进行不区分大小写的二进制搜索

时间:2012-02-29 15:57:03

标签: c++ stl

如果我有一个字符串向量,如何使用不区分大小写的比较对某个字符串进行二进制搜索?我想不出任何简单的方法。

7 个答案:

答案 0 :(得分:3)

为std :: sort提供一个比较函数,用小写字母对容器进行排序(使用boost string algos来帮助),

然后在已排序的向量上执行二进制字符串,再次提供不区分大小写的比较操作来执行此操作。

使用lambda表达式确实有帮助

如果使用find,则不必先进行排序,但如果要进行频繁搜索并且设置非常大,则速度很慢。

编辑:这是示例

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

auto comp=[](const std::string& a, const std::string& b){   
   return boost::ilexicographical_compare
                       <std::string, std::string>(a,b);
});

std::sort(vs.begin(), vs.end(), comp);
std::binary_search(vs.begin(), vs.end(), value_to_search_for, comp);

如果你不打算对列表进行排序,那么相同的比较函数也可以用于std :: find。

TESTED

http://en.cppreference.com/w/cpp/algorithm/find

http://en.cppreference.com/w/cpp/algorithm/binary_search

http://en.cppreference.com/w/cpp/algorithm/sort

答案 1 :(得分:0)

您可以使用find标头中的algorithm来查找容器中的特定值,但我认为它不使用二进制搜索算法(没有先决条件对容器进行排序在将其传递给find之前。可以找到更多详细信息here

binary_search还提供了algorithm,再次提供了更多详细信息here

答案 2 :(得分:0)

我认为你需要编写自己的比较函数,它将比较小写变体中的两个字符串。使用此函数,您可以对vector进行排序,然后通过这些比较器比较查询字符串。

答案 3 :(得分:0)

std::find不支持谓词参数,因此您要查找的正确算法为std::find_if

std::find_if( vec.begin(), vec.end(), InsensitiveCompare("search string") );

...其中InsensitiveCompare是一个函数,它返回true以进行不区分大小写的比较。例如:

struct InsensitiveCompare
{
  std::string comp;

  InsensitiveCompare( std::string const &s ) : comp(s) {}

  bool operator() ( std::string const &test ) const
  {
    // return true here if test compares with comp.
  }
}

答案 4 :(得分:0)

使用find_if来提供自定义谓词:

find_if (myvector.begin(), myvector.end(), MyPredicate);

http://www.cplusplus.com/reference/algorithm/find_if/

另请参阅此文章以获取有关编写可重用谓词的帮助: Making map::find operation case insensitive

答案 5 :(得分:0)

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <strings.h> // strncasecmp()

inline int icompare(std::string const& a, std::string const& b) {
    size_t a_len = a.size(), b_len = b.size();
    size_t cmp_len = std::min(a_len, b_len);
    // strncasecmp() is a non-standard function, use the one available for your platform.
    if(int r = strncasecmp(a.data(), b.data(), cmp_len))
        return r;
    return (a_len > b_len) - (a_len < b_len);
}

struct LessNoCase {
    bool operator()(std::string const& a, std::string const& b) const {
        return icompare(a, b) < 0;
    }
};

template<class Iterator, class T>
Iterator binary_search_caseless(Iterator beg, Iterator end, T const& value) {
    Iterator i = std::lower_bound(beg, end, value, LessNoCase());
    return i != end && !icompare(*i, value)
        ? i   // found
        : end // not found
        ;
}

int main() {
    char const* strings[] = {
        "abc",
        "def",
        "ghi"
    };

    std::vector<std::string> v(
        strings + 0,
        strings + sizeof strings / sizeof *strings
        );

    // prepare for binary search
    std::sort(v.begin(), v.end(), LessNoCase());

    // do the binary search
    std::cout << "index of 'abc' is " << binary_search_caseless(v.begin(), v.end(), "ABC") - v.begin() << '\n';
    std::cout << "index of 'ABC' is " << binary_search_caseless(v.begin(), v.end(), "ABC") - v.begin() << '\n';
    std::cout << "index of 'DEF' is " << binary_search_caseless(v.begin(), v.end(), "DEF") - v.begin() << '\n';
    std::cout << "index of 'xyz' is " << binary_search_caseless(v.begin(), v.end(), "xyz") - v.begin() << '\n';
}

输出:

./test
index of 'abc' is 0
index of 'ABC' is 0
index of 'DEF' is 1
index of 'xyz' is 3

答案 6 :(得分:0)

如果您只需要知道这样的元素是否存在,请使用std :: binary_search。如果您需要访问该元素并知道它的位置,请使用std :: lower_bound。