c++ - std::equal_range 提示 "sequence not ordered"

标签 c++ c++11 stl quicksort stl-algorithm

我需要帮助对元素 vector 进行排序,并随后处理排序 vector 上的范围。字符串 vector 最初使用默认运算符<谓词

进行排序

考虑以下未排序字符串 vector

std::vector<std::string> strings = {
   "1A", "3C1", "1B", "1C1", "4D", "1C1"
}

std::sort(strings.begin(), strings.end(), std::less  <std::string > );

排序后,最终会按词汇顺序将字符串排序为以下内容:

"1A", "1B", "1C1", "1C1", "3C1", "4D"

在我的例子中,我想迭代这些有序字符串,将它们分成范围[begin, end),使用第一个数字字符作为值比较器 - 我不知道如何在没有让 Visual Studio 指示“序列未排序”

"1A", "1B", "1C1", "1C1"

第二组应包含

"3C1"

和最后一组

"4D"

我一直在尝试使用 std::equal_range 使用仅搜索前导数字的谓词,但它一直指示“序列未排序”(编辑 - 这是我的一个错误因为我使用的比较器 equal_range 不尊重底层集合的现有顺序)。我认为这是因为现有的排序范围(使用 std::less 作为谓词与我提取子范围的谓词不同)是问题的根源。有关如何将此有序列表分解为子范围的任何帮助都会不胜感激。

编辑说明:虽然上面的问题已经得到解答,但我想用一个坚实的例子使问题更清楚,以便其他人可以了解我在哪里犹豫不决。我过度简化了我试图解决的问题,实际问题使用了一个具有 4 个字段(1 个可选)的类,因此,我没有提供足够的详细信息来显示 equal_range 参数(特别是我传递的值)的问题所在到相等的范围和相应的比较器中,该比较器用于根据该比较器对元素进行严格的弱排序 - 它还必须尊重基础集合的现有顺序)。事实证明,问题解决起来出奇的简单 - 我只需更改显式默认 PriorityValue 构造函数 - 将这 4 个参数传递给一个非显式构造函数,我可以将“channel”字段传递为单个 arg 构造函数参数。结果我对 equal_range 的调用如下:

// lambda to compare channels in ascending order 
const auto channelComp = [](const PriorityLevel& a, const PriorityLevel& b) {
    return a.getChannel() < b.getChannel();
};    

auto range = std::equal_range(gPriorities.begin(), gPriorities.end(), 1, channelComp);
// print all common channel entries
std::cout << "priorites with channel [1]" << std::endl;
std::cout << "Channel, PriorityChar, filename, [optional sequence]" << std::endl;
std::copy(range.first, range.second,
    std::ostream_iterator<PriorityLevel>(std::cout, "\n"));

我在 coliru中有一个活生生的例子 展示了我解决问题的位置 - 我希望这有用。

unsorted
Channel, PriorityChar, filename, [optional sequence]
1A[foo._dr]
3A[bar._dr]
1B[foo._dr]1
1B[bar._dr]1
1B[foo._dr]2
1B[bar._dr]2
1B[foo._dr]3
1B[foo._dr]3
1B[foo._dr]4
1B[foo._dr]5
2A[foo._dr]
2B[foo._dr]1
2B[foo._dr]2
2B[foo._dr]3
2B[foo._dr]2

sorted - ascending
Channel, PriorityChar, filename, [optional sequence]
1A[foo._dr]
1B[bar._dr]1
1B[bar._dr]2
1B[foo._dr]1
1B[foo._dr]2
1B[foo._dr]3
1B[foo._dr]3
1B[foo._dr]4
1B[foo._dr]5
2A[foo._dr]
2B[foo._dr]1
2B[foo._dr]2
2B[foo._dr]2
2B[foo._dr]3
3A[bar._dr]

priorites with channel [1]
Channel, PriorityChar, filename, [optional sequence]
1A[foo._dr]
1B[bar._dr]1
1B[bar._dr]2
1B[foo._dr]1
1B[foo._dr]2
1B[foo._dr]3
1B[foo._dr]3
1B[foo._dr]4
1B[foo._dr]5

priorites with channel [2]
Channel, PriorityChar, filename, [optional sequence]
2A[foo._dr]
2B[foo._dr]1
2B[foo._dr]2
2B[foo._dr]2
2B[foo._dr]3

最佳答案

这是一个工作示例:

#include <vector>
#include <string>
#include <algorithm>
#include <functional>
#include <iostream>
#include <ostream>

bool initial_char_comp( std::string const& s1, std::string const& s2)
{
    if (s1.size() == 0 || s2.size() == 0) {
        return s1.size() < s2.size();
    }

    return s1[0] < s2[0];
}


int main(int argc, char ** argv) {
    std::vector<std::string> strings = {
       "1A", "3C1", "1B", "1C1", "4D", "1C1"
    };

    std::sort(strings.begin(), strings.end(), std::less<std::string>());

    for (auto i = strings.cbegin(); i != strings.cend(); ++i) {
        std::cout << *i << " ";
    }

    std::cout << std::endl;

    for (char c = '1'; c < '5'; ++c) {
        auto range = std::equal_range( strings.cbegin(), strings.cend(), std::string(1, c), initial_char_comp);

        std::cout << "range starting with '" << c << "': "; 
        for (auto i = range.first; i != range.second; ++i) {
            std::cout << *i << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

关于c++ - std::equal_range 提示 "sequence not ordered",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25926415/

相关文章:

c++ - c++中tcp服务器中的多线程

c++ - 如何将一维数组与二维数组进行比较(C++)

c++ - 为什么 std::is_rvalue_reference 没有按照广告宣传的那样做?

c++ - Xcode 4.3 和 C++11 包含路径

c++ - 设置 std::vector 大小的正确方法

C++ 沿角度移动二维点

c++ - 如何在 Qt 应用程序中处理纯正则表达式结果?

c++ - 我可以通过将函数实现为类对象方法来避免使用互斥锁吗

c++ - 从容器中删除元素的单语句方法

c++ - 如果在 VC 编译器中包含诸如 std::map 之类的容器,类的内存布局是什么