如何优化自定义日期结构的比较功能?
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_queue
或 std::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
.
,我希望可以更容易理解
因此您可以初始化单独的 year
、month
和 day
组件并使用 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;
}
我想对 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_queue
或 std::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
.
因此您可以初始化单独的 year
、month
和 day
组件并使用 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;
}