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

时间:2016-11-19 12:18:47

标签: c++ algorithm sorting c++11 custom-object

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

#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功能看起来很糟糕。有什么想法我怎么能改进它?

3 个答案:

答案 0 :(得分:3)

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

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,因为我们不需要像std::sort()priority_queuestd::set那样覆盖STL容器的比较器提供整数返回码并使代码相对复杂。布尔就够了。

答案 1 :(得分:3)

我不是C ++专家,其他人指出std::sort()不需要三方比较,只需要<。但要按照书面清理代码:

您的compare_dates()继续对>/</==进行三方比较,并希望获得+1/-1/0返回值。因此,声明一个三向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);
} 

如果高阶比较给出&#39; ==&#39;,您只能进行低阶比较。因此,您可以避免使用所有其他条款,大括号和缩进,从而使您的缩进级别保持不变并且很容易在眼睛上。它还调出了计算的对称性。

答案 2 :(得分:0)

使用一天仅使用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;
 }