【问题标题】:Provide strict ordering during comparison with multiple fields在与多个字段进行比较时提供严格的排序
【发布时间】:2016-07-25 09:48:45
【问题描述】:

如何在具有大量可比较字段的对象之间提供严格的排序?

假设您有两个对象 xy 必须进行比较,每个对象都有 3 个字段(a、b、c)

bool less(x, y)
  return x.a < y.a || x.b < y.b || x.c < y.c

很好,但这提供了弱排序。如果 x.a less(x,y) 为真,less(y, x) 也为真。

我习惯写作

bool less(x, y)
  return x.a < y.a || (x.a == y.a && x.b < y.b)

但一旦涉及的字段数量增加,它就会变得非常难看。

bool less(x, y)
  return x.a < y.a || 
        (x.a == y.a && x.b < y.b) ||
        (x.a == y.a && x.b == y.b && x.c < y.c) ||
        (x.a == y.a && x.b == y.b && x.c == y.c && x.d < y.d);

有人有更好看的算法吗?

【问题讨论】:

  • 我认为你需要定义什么是最重要的领域,什么是次要的。订购应该(我认为)精确确定。基本上,你首先检查什么属性,第二个是什么,第三个是什么?
  • 我很想这样做,但由于问题的性质,比较必须以某种方式考虑每个字段
  • 另一种选择是创建一个函数,对三个(或四个,或十个)属性进行一些计算,为您提供一个值,that 就是您比较的值。像val_to_compare = 1*a + 10*b + 23*c 这样的东西。这为您提供了一种将权重附加到属性的方法。
  • 这是关于 Java 还是 C++ 的问题?
  • 将属性(引用/指向它们的指针)存储在数组中,然后使用循环 - 使用正确的优化级别,您的编译器将展开它。

标签: c++ algorithm language-agnostic boolean-logic


【解决方案1】:

如果您使用的是 C++11 或更高版本,有一个很好的技巧可以让您无需手动编写 SWO。您可以使用std::tuple 来打包您的成员,并且std::tupleoperator&lt; 实现为字典顺序。

所以你可以写这个

struct foo {
    int x, y, z;

    bool operator<(const foo& rhs) const {
        return std::tie(x, y, z) < std::tie(rhs.x, rhs.y, rhs.y);
    }
};

和 struct foo 将按字典顺序按 x、y、z 进行比较。这个还有很多要写的,大家可以改进一下

struct foo {
    int x, y, z;

    auto tied() const {
        return std::tie(x, y, z);
    }

    bool operator<(const foo& rhs) const {
        return tied() < rhs.tied();
    }
};

如果你有很多成员,这可以节省很多打字,但它假设 C++14(对于 C++11,你必须手动写出 tied 的返回类型)。

【讨论】:

  • 非常好的方法。感谢分享。
【解决方案2】:

我通常这样做:

bool operator< (type x, type y) {
    if (x.a < y.a) return true;
    if (x.a > y.a) return false;

    if (x.b < y.b) return true;
    if (x.b > y.b) return false;

    return x.c < y.c;
}

这提供了硬排序并扩展了您关心的任意数量的元素,而不会增加每个元素的开销。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-13
    • 1970-01-01
    • 1970-01-01
    • 2021-05-02
    • 2016-04-23
    • 2019-11-07
    • 1970-01-01
    相关资源
    最近更新 更多