【问题标题】:Order vector of enum by their value枚举的顺序向量按其值
【发布时间】:2017-05-17 10:20:04
【问题描述】:

我有一个枚举类,它有 4 个不同的值。 ABCD

我无法控制底层类型是什么。

我有一个枚举向量,我想订购它,所以所有A 都是第一个。然后是所有B,然后是所有C,最后是所有D

我可以用很长的 if 语句来做到这一点。但我想知道是否有一种简单的惯用方法来实现这一点。

编辑:你误解了我想要的。我有一个这样的枚举类:

enum class MyEnum { A = 3, B = 1, C = 4, D = 2};

我有一个这个枚举的向量,我想订购以便 A 在 B 之前在 C 之前在 D 之前。

std::sort 在这里根本没有帮助。

【问题讨论】:

  • how to sort STL vector的可能重复
  • 约翰,你能作为你的班级一起工作吗?
  • std::sort 可以,但您必须编写自己的比较。
  • @BoPersson 是的,请启发如何在不引起大量比较的情况下做到这一点

标签: c++ sorting enums


【解决方案1】:

一种避免“切换”方法或表驱动比较的运行时效率更高的方法是:

inline bool operator<(MyEnum left, MyEnum right) {
  return static_cast<std::underlying_type_t<MyEnum>>(left) < static_cast<std::underlying_type_t<MyEnum>>(right);
}

用于需要通过 std::less 对枚举进行排序或排序(例如 std::sort)的上下文。

如果您愿意,您可以将这种比较模板化,以便它影响每个枚举(或者可能每个具有某些识别特征的枚举,以减少混乱)。 “每个枚举”方法可能看起来像这样:

template <typename T, typename N=std::enable_if_t<std::is_enum_v<T>>>
inline bool operator<(T left, T right) {
  return static_cast<std::underlying_type_t<T>>(left) < static_cast<std::underlying_type_t<T>>(right);
}

上面的代码将按照每个枚举器的赋值进行排序。如果你想要一个不同的排序顺序,你可以使用查找而不是使用 std::underlying_type,也许使用这样的哈希表:

inline bool operator<(MyEnum left, MyEnum right) {
  static std::unordered_map<MyEnum, int> ORDER = {
    {MyEnum::A, 1}, {MyEnum::B, 2}, {MyEnum::C, 3}, {MyEnum::D, 4}
  };
  return ORDER[left] < ORDER[right];
}

【讨论】:

    【解决方案2】:

    C++ 不能根据名称对值进行排序,只能根据值进行排序,因此您必须提供一个映射到您希望它排序的顺序。要么使用表格,要么使用排名函数,例如:

    enum class MyEnum { A = 3, B = 1, C = 4, D = 2};
    
    int rank(MyEnum value)
    {
        switch (value)
        {
        case MyEnum::A:
            return 1;
    
        case MyEnum::B:
            return 2;
    
        case MyEnum::C:
            return 3;
    
        case MyEnum::D:
            return 4;
        }
    }
    
    bool operator<(MyEnum left, MyEnum right)
    { return rank(left) < rank(right); }
    

    现在std::sort(v.begin(), v.end()) 应该适用于MyEnums 的向量。

    如果您不希望在排序之外以这种方式比较枚举,您可以将operator&lt; 转换为函子并将其传递给sort

    【讨论】:

      猜你喜欢
      • 2012-06-16
      • 2016-01-27
      • 2011-05-27
      • 2014-07-11
      • 1970-01-01
      • 2021-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多