сортировка — C ++ получить даты между двумя датами

Я помещаю каждую дату в вектор структуры (vector<value>) :

struct value {
string code;
string date;
string name;
};

Формат дат: «ГГГГ-ММ-ДД ЧЧ: ММ: СС»

Я хочу получить даты между двумя указанными датами (например, с 01.01.2016 по 01.02.2016). Как я могу это сделать?

0

Решение

Эта проблема имеет две стороны:

  1. Как вы получаете сортируемые значения даты из строковых представлений
  2. Как вы можете эффективно сортировать указанные значения.

Поиск действительных меток времени из строки даты

C ++ использует объект time_t в качестве допустимого количества секунд от установленной даты (1 января 1970 г. UTC) Есть много краткой информации об этом, в каждом случае вы можете считать это целочисленным представлением времени в секундах.

Далее вам нужно знать, как анализировать ваши данные в метке времени: вот несколько полезных ссылок.

Мой предпочтительный метод указываете ей — есть пример этого Здесь на переполнение стека. Также это Кажется, кто-то еще прошел тот же курс, что и вы;)

Вы можете рассмотреть возможность использования Функция вашего собственного дизайна, если формат даты необычный. В этом случае, используя зсапЕ часто это самый простой способ — интерфейс этой функции несколько старомоден в стиле «c», но это не меняет того простого факта, что он работает, и хорошо.
Вот ссылка на того, кто читает простую дату с помощью scanf.

Оказывается, код, который я написал ниже, близок к Ответ на этот великий вопрос

#include <stdio.h>
#include <time.h>
time_t GetDateFromObject(value & Date_Object)
{
char * Date_String = Date_Object.date.c_str();
int year, month, day, hour, minute, second;
if(sscanf(Date_String , "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second) == 6)
{
time_t rawTime;
time(&rawTime);
struct tm * parsedTime;
parsedTime = localtime(&rawTime);

// tm_year is years since 1900
parsedTime->tm_year = year - 1900;
// tm_months is months since january
parsedTime->tm_mon = month - 1;
parsedTime->tm_mday = day;
parsedTime->tm_hour = hour;
parsedTime->tm_min = minute;
parsedTime->tm_sec = second;
return mktime(parsedTime);
}
}

Ассоциация и сортировка дат

Как только вы узнаете, как получить time_t из вашей даты, вы можете начать создавать ассоциативный массив данных — в этом случае я буду использовать карта.

Ниже приведен пример использования карты для вставки, сортировки и вывода данных.

#include<iostream>
#include<map>
#include<vector>
#include<ctime>

struct value {
std::string code;
std::string date;
std::string name;
};

void Print_Range(std::vector<value> & Data, value & Date_Start, value & Date_end)
{
std::map<time_t, value *> Associated_Data;
for(auto Date_Object : Array_Of_Dates)
{
time_t Object_Time = GetDateFromObject(Date_Object);
Associated_Data.insert(std::make_pair(Object_Time, & Date_Object);
}
//as the std::map is sorted by-default,
//we can know locate the iterator for any two time codes
time_t Search_From = GetDateFromObject(Date_Start);
time_t Search_To = GetDateFromObject(Date_End);
auto Start_IT = Associated_Data.find(Search_From);
auto End_IT = Associated_Data.find(Search_To);

std::cout << "Printing all dates in range \n";
for(auto IT=Start_IT; IT != End_IT; IT++)
{
std::cout << IT->Second->date << '\n';
}
}

Заметки:

  1. Я использую синтаксис C ++ 11 здесь, если вы не понимаете Петли на основе диапазона Вы можете прочитать их.
  2. Я предполагаю, что структура, которую вы описали, хранится в вектор.
  3. Функция «GetDateFromObject», которую я здесь использую, является заполнителем для любой функции, которую вы используете для получения метки времени)
  4. Вставка данных в карту с использованием std :: make_pair.
  5. Я держу указатели на оригинальные объекты-значения.
1

Другие решения

Формат даты YYYY-MM-DD HH:MM:SS отличается тем, что лексикографическое (буквенно-буквенное) сравнение такое же, как сравнение по времени, так что вы можете просто использовать это.

Если ваш контейнер изначально не отсортирован по дате, вам придется просмотреть все даты по очереди. std::copy_if обеспечивает хороший способ сделать это:

std::vector<value> get_between(const std::vector<value>& v,
const std::string& from, const std::string& to)
{
std::vector<value> u;
std::copy_if(v.begin(), v.end(), std::inserter(u, u.begin()),
[from,to](const auto& val) {
return val.date >= from && val.date <= to;
});
return u;
}

copy_if просматривает [v.begin(), v.end()[ и погружает элементы в u от u.begin() и далее всякий раз, когда лямбда возвращает истину. Они будут в том же порядке, что и вы.

Если ваш диапазон отсортирован, вы можете использовать std::lower_bound а также std::upper_bound вместо этого получить начальный и конечный итераторы:

std::vector<value> get_between(const std::vector<value>& v,
const std::string& from, const std::string& to)
{
value fromv { "", from, "" };
auto begin = std::lower_bound(v.begin(), v.end(), fromv,
[](const auto& lhs, const auto& rhs) {
return lhs.date < rhs.date;
});

value tov { "", to, "" };
auto end = std::upper_bound(begin, v.end(), tov,
[](const auto& lhs, const auto& rhs) {
return lhs.date < rhs.date;
});

return std::vector<value>(begin, end);
}

lower_bound а также upper_bound найти первое значение по крайней мере from и первое значение больше, чем toтак что диапазон [lb, ub[ это диапазон со значениями [from, to],

2

Например, вы можете сделать так: преобразовать все даты в time_t значение (числовое представление даты и времени), а затем переберите свой вектор и используйте нормальное сравнение между тремя числами time_t. Для справки: man mktime, man strptime,

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector