Фильтровать массив дат в F#
У меня есть массив, содержащий даты без выходных (не обязательно рабочих дней). Теперь я хочу только одну дату в месяц и только с определенного дня. Если день не существует в массиве, следующий результирующий день должен быть в результирующем списке.
Например: дан массив: 1.2.2010, 2.2.2010, 5.2.2010, 6.2.2010, ..., 1.3.2010, 2.3.2010, ..., 1.4.2010, 4.4.2010
Я хочу, чтобы все даты 2-го числа каждого месяца
Результат: 2.2.2010, 2.3.2010, 4.4.2010
Как мне это сделать в F#? Пожалуйста, предоставьте обучающее и хорошее решение, я пытаюсь выучить F#. Я знаю, как сделать это в обязательном порядке:)
Спасибо!:D
2 ответа
Решение
Вот одно из возможных решений:
// Your input list with dates
let input = [DateTime.Now]
// We want 2nd day or later
let number = 2
input
// First, create group of dates for every Year/Month
// (so that all days in specifc month are in a single group)
|> Seq.groupBy (fun dt -> dt.Year, dt.Month)
|> Seq.map (fun ((y, m), dates) ->
// We want only dates that are later (or equal to) this 'limit'
let limit = new DateTime(y, m, number)
// Remove dates before the limit and then select minimal date
dates |> Seq.filter (fun d -> d >= limit) |> Seq.min)
Вот еще один (при условии отсортированного ввода):
type DateTime = System.DateTime
let filterDayOrFollowing day (input:DateTime[]) =
(input, ([], None))
||> Array.foldBack (fun date (acc, following:DateTime option) ->
if date.Day = day then date::acc, None
else match following with
| Some f when date.Year = f.Year
&& date.Month = f.Month
&& date.Day < day -> f::acc, None
| _ -> acc, Some date)
|> fst
let expected = [ DateTime(2010, 2, 2)
DateTime(2010, 3, 2)
DateTime(2010, 4, 4) ]
let actual =
[| DateTime(2010, 2, 1)
DateTime(2010, 2, 2)
DateTime(2010, 2, 5)
DateTime(2010, 2, 6)
DateTime(2010, 3, 1)
DateTime(2010, 3, 2)
DateTime(2010, 4, 1)
DateTime(2010, 4, 4) |]
|> filterDayOrFollowing 2
actual = expected |> printfn "actual = expected: %b"