Как я могу оптимизировать функцию сравнения для пользовательской структуры даты?

Я хочу отсортировать вектор dates и я написал функцию сравнения для него:

#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 Функция выглядит ужасно. Есть ли идея, как я могу улучшить это?

0

Решение

Я не эксперт по С ++, а другие указывают, что 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);
}

Вы можете выполнить сравнение более низкого порядка только в том случае, если сравнение более высокого порядка дало ‘==’. Таким образом, это позволяет вам избегать всех других выражений, скобок и отступов, что поддерживает постоянный уровень отступа и не вызывает проблем. Это также вызывает симметрию вычислений.

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 отдельно как для переопределения компаратора контейнеров STL типа std::sort(), priority_queue или же std::set нам не нужно предоставлять целочисленный код возврата и делать код достаточно сложным. Булева достаточно.

3

Как насчет использования того факта, что в день используется только 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;
}

— РЕДАКТИРОВАТЬ —

Как указал Кристиан Хакл, этот кодекс немного неясен.

Я надеюсь, что это может быть более понятным, если вы переведете часть битового поля в 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;
}
0
По вопросам рекламы [email protected]