std::equal_range抱怨"sequence not ordered"



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

考虑以下未排序字符串的向量

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指示"sequence not ordered"的情况下做到这一点

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

第二组应该包含

"3C1"

最后一组

"4D"

我一直在试验std::equal_range,使用一个只搜索前导数字的谓词,但它一直指示"sequence not ordered"(EDIT-这是我遇到的一个错误,因为我使用了一个不尊重基础集合现有顺序的比较器来equal_rrange)。我认为这是因为现有的排序范围(使用std::less作为谓词与我的谓词不同来提取子范围)是问题的根源。关于如何将这个排序列表分解为子范围的任何帮助都将不胜感激。

编辑注意:虽然上面的问题已经回答了,但我想用一个坚实的例子让问题更清楚,这样其他人就可以了解我的不足之处。我过于简化了我试图解决的问题,实际问题使用了一个有4个字段(1个可选)的类,因此,我没有提供足够的细节来显示我在哪里遇到了equal_range参数的问题(特别是我传递到equal_rrange的值和相应的比较器,该比较器用于根据该比较器对元素进行严格的弱排序,该比较器还必须尊重基础集合的现有顺序)。事实证明,这个问题解决起来出奇地简单——我只需要更改显式默认的PriorityValue构造函数——将这4个arg带到一个非显式构造函数中,在那里我可以将"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;
}

相关内容

  • 没有找到相关文章

最新更新