Как я могу перечислить отсутствующие даты из массива не непрерывных дат в Java? - PullRequest
2 голосов
/ 07 декабря 2008

У меня есть таблица данных, отсортированная по дате, из которой пользователь может выбрать набор данных, указав дату начала и окончания. Сами данные не являются непрерывными, потому что у меня нет данных на выходные и праздничные дни.

Я хотел бы иметь возможность перечислить все дни, для которых у меня нет данных в извлеченном наборе данных. Есть ли в Java простой способ:

  1. Вот упорядоченный массив дат.
  2. Это выбранная дата начала. (Первая дата в массиве не всегда является начальной датой)
  3. Это выбранная дата окончания. (Последняя дата в массиве не всегда является конечной датой)
  4. Возвращает список дат, у которых нет данных.

Ответы [ 4 ]

2 голосов
/ 07 декабря 2008

Вы можете создать временный список и при необходимости x его.

(Не фактическая Java. Извините, моя память об этом ужасна.)

dates = [...]; // list you have now;

// build list
unused = [];
for (Date i = startdate; i < enddate; i += day) {
    unused.push(i);
}

// remove used dates
for (int j = 0; j < dates.length; j += 1) {
    if (unused.indexOf((Date) dates[j]) > -1) { // time = 00:00:00
        unused.remove(unused.indexOf((Date) dates[j]));
    }
}
1 голос
/ 07 декабря 2008

Вы должны быть в состоянии создать отфильтрованный итератор, который обеспечивает это. Возможно, метод для итератора примет дату начала и окончания вашей коллекции. Что касается фактической реализации итератора, я не могу придумать ничего более изящного, чем грубое выполнение всей коллекции после обнаружения начального элемента.

0 голосов
/ 07 декабря 2008

В то время как другие ответы, которые уже даны, выглядят довольно простыми и приятными и содержат некоторые хорошие идеи (я особенно согласен с предложением Итератора от Nerdfest), я решил в любом случае дать этому шанс и написать решение, чтобы показать, как я я бы сделал это для первой итерации, я уверен, что есть возможность улучшить то, что ниже.

Я также, возможно, воспринял ваши требования слишком буквально, но вы знаете, как настроить код по своему вкусу. Ох и простите за ужасное именование объектов. Кроме того, поскольку в этом примере используется Calendar, помните, что Calendar.roll () в некоторых случаях может не обновлять весь объект Calendar, так что это потенциальная ошибка.

protected List<Calendar> getDatesWithNoData(Calendar start, Calendar end,
        Calendar[] existingDates) throws ParseException {

    List<Calendar> missingData = new ArrayList<Calendar>();

    for(Calendar c=start ; c.compareTo(end)<=0 ; c.roll(Calendar.DAY_OF_MONTH, true) ) {

        if(!isInDataSet(c, existingDates)) {
            Calendar c2 = Calendar.getInstance();
            c2.setTimeInMillis(c.getTimeInMillis());

            missingData.add(c2);
        }
    }
    return missingData;
}

protected boolean isInDataSet(Calendar toSearch, Calendar[] dataSet) {
    for(Calendar l : dataSet) {
        if(toSearch.equals(l)) return true;
    }
    return false;
}
0 голосов
/ 07 декабря 2008

Вы можете либо создать список всех возможных дат между начальной и конечной датой, а затем удалить даты, которые появляются в списке данных (лучше всего работает при отсутствии большинства дат), или вы можете начать с пустого списка дат и добавьте те, которые не отображаются в данных.

В любом случае, вы в основном перебираете диапазон дат между начальной и конечной датами, отслеживая, где вы находитесь в списке данных дат. Вы можете думать об этом как о «подобной слиянию» операции, когда вы проходите через два списка параллельно, обрабатывая записи, которые появляются в одном списке, но не в другом. В псевдокоде версия пустого списка может быть:

# given   - array of given dates
# N       - number of dates in given array
# missing - array of dates missing

i = 0;    # Index into given date array
j = 0;    # Index into missing data array
for (current_date = start_date; current_date <= end_date; current_date++)
{
    while (given[i] < current_date && i < N)
        i++
    if (i >= N)
        break
    if (given[i] != current_date)
        missing[j++] = current_date
}
while (current_date < end_date)
{
    missing[j++] = current_date
    current_date++
}

Я предполагаю, что тип даты квантуется в единицах дня; то есть date + 1 (или date++) - это день после date.

...