为带有带前缀的字符串的容器查找相等的范围

Find equal range for container with string with prefix

本文关键字:查找 范围 字符串 前缀      更新时间:2023-10-16

我有 2 个迭代器 range_begin,range_end,它们是我的容器。我需要找到所有以字符前缀开头的字符串。 这是我的代码:

template <typename RandomIt>
pair<RandomIt, RandomIt> FindStartsWith(
RandomIt range_begin, RandomIt 
range_end,char prefix){
auto it=equal_range(range_begin,range_end,prefix,
[prefix](const string& city){return city[0]==prefix;});
return it;}

例如,对于

const vector<string> sorted_strings = {"moscow", "murmansk", "vologda"};
auto it=FindStartsWith(strings.begin(),strings.end(),'m');

我想先在"莫斯科"上获得迭代器,在"摩尔曼斯克"之后获得最后一个迭代器。

我收到奇怪的编译器错误。出了什么问题,我该如何解决这个问题?我无法编写正确的 lambda 比较器。

equal_range需要一个接受两个参数的比较函数;你传递的是一个接受一个参数的函数。

异构调用(value的类型与区域中的类型元素不同)需要一个比较函数,该函数可以按任一顺序采用这两种类型。在这种情况下,lambda 不起作用,因为它只有一个operator()重载。

最后,该函数必须执行小于类型的比较,而不是相等的比较。粗略地说,equal_range返回从!(element < value)的第一个元素到value < element的第一个元素的范围。

您的错误可能是由于字符串.begin()和.end()没有sorted_造成的。我认为您也不应该使用模板。 撇开错误不谈,我建议您使用不同的 std 函数。一个更简单的解决方案是使用 foreach:

#include <algorithm>
#include <iterator>
#include <list>
#include <string>
#include <utility>
#include <vector>
typedef std::vector<std::string>::const_iterator RandomIt;
std::vector<std::string> FindStartsWith(RandomIt start, RandomIt end, const char prefix) {
std::vector<std::string> result;
std::for_each(start, end, [&](auto city) {
if (city.front() == prefix) {
result.push_back(city);
}
});
return result;
}
int main(int argc, char* argv[]) {
const std::vector<std::string> sorted_strings = { "moscow", "murmansk", "vologda" };
auto prefix_cities = FindStartsWith(sorted_strings.begin(), sorted_strings.end(), 'm');
return 0;
}

绝对可以使用重构,但我假设您需要出于其他原因在 FindStartsWith 中实现它......

感谢您的发布,这教会了我很多关于equal_range :)

答案:

编译错误的原因隐藏在比较器的两个函数"lower_bound"和"upper_bound"的实现中,这两个函数从主函数"equal_range"调用。

  1. EQUAL_RANGE

    template<class ForwardIt, class T, class Compare>
    pair<ForwardIt,ForwardIt> 
    equal_range(ForwardIt first, ForwardIt last,
    const T& value, Compare comp)
    {
    return make_pair(lower_bound(first, last, value, comp),
    upper_bound(first, last, value, comp));
    }
    

注意比较器在每个函数中的产生方式。请注意,比较器是由不同的参数序列引起的,这就是错误的原因。

  1. LOWER_BOUND:

    if (comp(*it, value))
    
  2. UPPER_BOUND:

    if (!comp(value, *it))
    

附加预示

下面我相应地复制了两个函数的实现示例。

LOWER_BOUND:

```
template<class ForwardIt, class T, class Compare>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp)
{
ForwardIt it;
typename std::iterator_traits<ForwardIt>::difference_type count, step;
count = std::distance(first, last);

while (count > 0) {
it = first;
step = count / 2;
std::advance(it, step);
if (comp(*it, value)) {
first = ++it;
count -= step + 1;
}
else
count = step;
}
return first;
}
```

UPPER_BOUND:

```
template<class ForwardIt, class T, class Compare>
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp)
{
ForwardIt it;
typename std::iterator_traits<ForwardIt>::difference_type count, step;
count = std::distance(first, last);

while (count > 0) {
it = first; 
step = count / 2;
std::advance(it, step);
if (!comp(value, *it)) {
first = ++it;
count -= step + 1;
} 
else
count = step;
}
return first;
}
```

溶液

您有两种方法可以解决此问题(也许更多)。

  1. 为每个函数编写两个比较器,并分别调用对方。
  2. char参数转换为字符串,为字符串编写比较器并调用equal_range。