【问题标题】:std::equal_range complains about "sequence not ordered"std::equal_range 抱怨“序列未排序”
【发布时间】:2014-09-19 04:31:49
【问题描述】:

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

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

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) 使用第一个数字字符作为值比较器 - 我不知道如何做到这一点让视觉工作室指示“序列未排序”

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

第二组应该包含

"3C1"

最后一组

"4D"

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

编辑注释:虽然上述问题已得到解答,但我想通过一个可靠的示例使问题更清楚,以便其他人可以了解我步履蹒跚的地方。我过度简化了我试图解决的问题,实际问题使用了一个具有 4 个字段(1 个可选)的类,因此,我没有提供足够的细节来显示我在使用 equal_range 参数时遇到的问题(特别是我传递的值)进入相等的范围和相应的比较器,该比较器用于根据此比较器对元素进行严格的弱排序 - 这也必须尊重基础集合的现有顺序)。事实证明,这个问题的解决非常简单——我只需要更改显式的默认 PriorityValue 构造函数——将这 4 个参数带到一个非显式构造函数中,我可以在其中将“通道”字段传递为单个 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

【问题讨论】:

  • 为什么不发布一些代码而不是描述它?
  • 代码不是很好,我看看能不能让它进入半工作状态。我通常会发送 coliru 链接 - 让我看看在接下来的半小时内我能做什么
  • 至少,将您使用的谓词与equal_range 一起发布。
  • 不幸的是我想写的谓词,这是我的 coliru 在预测上失败的努力 - 我的谓词基本上搜索第一个匹配项而不是第一个字符匹配项,我认为 Michael Burr 的谓词可能虽然工作。如果对这里感兴趣的是我的现场示例 - 与提出的问题略有不同,因为它有太多我想避免的细节coliru.stacked-crooked.com/a/ef44fd8b5cc45ad6

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


【解决方案1】:

这是一个工作示例:

#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;
}

【讨论】:

  • 非常好,我会尝试将它应用到我的实时示例中-您可以看到为什么我没有发布实时示例,感谢在我的问题中的字里行间阅读-顺便说一句,这里是实时示例我的问题试图用更简单的术语描述coliru.stacked-crooked.com/a/ef44fd8b5cc45ad6 :)
  • @johnco3:链接上发布的代码似乎没有按照您在这个问题中的描述进行 - 它使用std::greater&lt;PriorityLevel&gt;() 进行排序,其中涉及比较中类的所有成员字段,然后使用相同的std::greater&lt;PriorityLevel&gt;() 比较器执行equal_range 操作。它不会显示您询问的错误消息 - 它只是选择并显示与值匹配的单个元素(应该如此)。
  • 我描述的错误消息实际上是在 windows 上,而 coliru 使用 gcc - 我认为 windows 上错误的原因是 stl 中的调试标志有一些安全防护来检测严格的弱排序和版本有那个错误我正在使用与 std::greater() 不同的谓词来尝试匹配通道前导数字,无论如何我尝试采用类似于您的比较器的东西,看起来它需要构造一个来自数字实体的 PriorityLevel - 有一些错误 coliru.stacked-crooked.com/a/c6cd57bae2f0b1d6
  • 谢谢 Michael - 我发布了我的代码的更新工作版本 - 问题是我使用了带有默认参数的显式构造函数,我应该允许默认的简单通道值来构造 PriorityLevel 对象。这样,我们总是在比较 PriorityLevels。在 coliru coliru.stacked-crooked.com/a/ca599ff5b23bc9ec 中的代码
猜你喜欢
  • 2014-10-15
  • 1970-01-01
  • 1970-01-01
  • 2017-03-11
  • 2017-01-17
  • 2013-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多