如何优化自定义日期结构的比较功能?

How can I optimize compare function for custom date structure?

我想对 date 的向量进行排序,我为它编写了比较函数:

#include <iostream>

struct date {
    int day;
    int month;
    int year;
};

int compare_dates(date a, date b) {
    if (a.year < b.year) {
        return -1;
    } else if (a.year == b.year) {
        if (a.month < b.month) {
            return -1;
        } else if (a.month == b.month) {
            if (a.day < b.day) {
                return -1;
            } else if (a.day > b.day) {
                return 1;
            }
        } else {
          return 1;
        }
    } else {
        return 1;
    }

    return 0;
}

int main() {
    date a = {};
    date a.day = 19;
    date a.month = 11;
    date a.year = 2016;

    date b = {};
    date b.day = 20;
    date b.month = 11;
    date b.year = 2016;

    compare_dates(a, b) // -1
    compare_dates(b, a) // 1
    compare_dates(b, b) // 0

    return 0;
}

它运行良好,但 compare_dates 功能看起来很糟糕。有什么想法可以改进它吗?

这足以将日期容器按升序排序:

bool compareDates(date const& lhs, date const& rhs) const {
    if(lhs.year == rhs.year) {
        if(lhs.month == rhs.month) {
            return lhs.day < rhs.day;
        }
        return lhs.month < rhs.month;
    }
    return lhs.year < rhs.year;
}

// sort(dates, dates + n, compareDates);

编辑

我故意没有单独处理 -1 作为 STL 容器的覆盖比较器,例如 std::sort()priority_queuestd::set 我们不需要提供整数return 代码并使代码相对复杂。布尔值就足够了。

我不是 C++ 专家,其他人指出 std::sort() 不需要三向比较,只需要一个 <。但是要清理你写的代码:

您的 compare_dates() 一直在对 >/</== 进行三向比较,并且想要一个 +1/-1/0 return 值。因此,声明一个三向 cmp() 辅助函数来执行此操作,就像我们在 Python 中所做的那样。现在您的代码缩减为:

int cmp(int x, int y) {
    return (x>y) ? 1 : ((x<y) ? -1 : 0); 
}

int compare_dates(date a, date b) {
    if (cmp(a.year, b.year) != 0)
        return cmp(a.year, b.year);

    if (cmp(a.month, b.month) != 0)
        return cmp(a.month, b.month);

    return cmp(a.day, b.day);
} 

如果高阶比较给出“==”,您只会陷入低阶比较。这样一来,您就可以避免所有其他子句、大括号和缩进,从而使缩进级别保持不变,并且看起来很容易。它还指出了计算的对称性。

一天只用4位,一个月只用5位呢?

#include <iostream>

struct date
 {
    int day;
    int month;
    int year;
 };

int compare_dates (date a, date b)
 {
   long  da { (a.year << 9) + (a.month << 4) + a.day };
   long  db { (b.year << 9) + (b.month << 4) + b.day };

   return da < db ? -1 : (da > db);
 }

int main()
 {
    date a = { 19, 11, 2016 };
    date b = { 20, 11, 2016 };

    std::cout << compare_dates(a, b) << std::endl; // print -1
    std::cout << compare_dates(b, a) << std::endl; // print 1
    std::cout << compare_dates(b, b) << std::endl; // print 0

    return 0;
 }

--- 编辑 ---

正如 Christian Hackl 所指出的,这段代码有点晦涩难懂。

如果您将 date 结构中的位域部分转换为 union.

,我希望可以更容易理解

因此您可以初始化单独的 yearmonthday 组件并使用 full 组件进行比较。

内容如下

#include <iostream>

union date
 {
   struct
    {
      unsigned long day    : 5U;
      unsigned long month  : 4U;
      unsigned long year   : 23U;
    } s ;

   unsigned long full;
 };

int compare_dates (date const & a, date const & b)
 { return a.full < b.full ? -1 : (a.full > b.full); }

int main()
 {
    date a = { { 19, 11, 2016 } };
    date b = { { 20, 11, 2016 } };

    std::cout << compare_dates(a, b) << std::endl; // print -1
    std::cout << compare_dates(b, a) << std::endl; // print 1
    std::cout << compare_dates(b, b) << std::endl; // print 0

    return 0;
 }