Использование F# match для извлечения двух дней из недели
Учусь использовать F#, и я пытаюсь познакомиться с выражением соответствия. Я ожидаю, что приведенный ниже код выберет два последовательных дня недели, текущий день и следующий день. Это только выбирает текущий день. Что мне здесь не хватает?
Массив DayOfWeek:
let days = [|DayOfWeek.Sunday, true;
DayOfWeek.Monday, false;
DayOfWeek.Tuesday, true;
DayOfWeek.Wednesday, true;
DayOfWeek.Thursday, true;
DayOfWeek.Friday, true;
DayOfWeek.Saturday, true;|]
Выражение соответствия:
let curDate = DateTime.Now
let validDates =
[
for i in days do
match i with
| day, true ->
match day with
| x when int x = int curDate.DayOfWeek ||
int x > int curDate.DayOfWeek
&& int x - int curDate.DayOfWeek = 1 ->
yield
x
| _ -> ()
|_ -> ()
]
3 ответа
Для меня проблема заключается в использовании сопоставления с образцом.
Вот как бы я это сделал, позволив вам занять любое количество дней, а не только два.
open System
let next count days day =
seq { while true do yield! days } // make the days array infinite
|> Seq.skipWhile (fun (d, _) -> d <> day) // skip until we find our day
|> Seq.filter (fun (_, incl) -> incl) // get rid of 'false' days
|> Seq.take count // take the next 'count' of days
|> Seq.map (fun (d, _) -> d) // we only care about the day now, so a simple map gets rid of the boolean
Используя ваш массив дней, я получаю следующее:
DayOfWeek.Sunday
|> next 2 days
val it : seq<DayOfWeek> = seq [Sunday; Tuesday]
а также
DayOfWeek.Thursday
|> next 3 days
val it : seq<DayOfWeek> = seq [Thursday; Friday; Saturday]
а также
DayOfWeek.Sunday
|> next 10000 days
|> Seq.iter (printfn "%A")
Ну, я не собираюсь печатать то, что делает этот, вам просто нужно использовать свое воображение.:)
Надеюсь, это поможет!
Изменить Я сделал это обрабатывать бесконечное количество дней.
Ваше решение кажется мне чрезвычайно запутанным, и, как другие уже упоминали, оно работает, только если базовое значение int завтрашнего дня DayOfWeek больше, чем сегодняшнее. Как вы знаете, неделя - это цикл, поэтому логика не всегда справедлива. Я не хочу кормить с ложечки, но есть гораздо более простое решение:
let today = DateTime.Now.DayOfWeek
let days = [|DayOfWeek.Sunday, true;
DayOfWeek.Monday, false;
DayOfWeek.Tuesday, true;
DayOfWeek.Wednesday, true;
DayOfWeek.Thursday, true;
DayOfWeek.Friday, true;
DayOfWeek.Saturday, true;|]
let today_and_tomorrow =
let idx_today = Array.findIndex (fun (day, _) -> day = today) days
days.[idx_today], days.[idx_today + 1 % days.Length]
Я думаю, что вы можете написать это намного проще, используя Enum-caps из F#/.NET:
open System;;
let weekdayAfter (day : DateTime) : DayOfWeek =
int day.DayOfWeek
|> (fun i -> (i+1) % 7)
|> Microsoft.FSharp.Core.LanguagePrimitives.EnumOfValue<_, _>
let today_and_tomorrow =
let today = DateTime.Today
(today.DayOfWeek, weekdayAfter today)
И если вы действительно хотите использовать сопоставление с шаблоном, то почему бы не использовать удобочитаемое / очевидное решение:
let dayAfter (day : DateTime) =
match day.DayOfWeek with
| DayOfWeek.Sunday -> DayOfWeek.Monday
| DayOfWeek.Monday -> DayOfWeek.Tuesday
| DayOfWeek.Tuesday -> DayOfWeek.Wednesday
| DayOfWeek.Wednesday -> DayOfWeek.Thursday
| DayOfWeek.Thursday -> DayOfWeek.Friday
| DayOfWeek.Friday -> DayOfWeek.Saturday
| DayOfWeek.Saturday -> DayOfWeek.Sunday
| _ -> failwith "should never happen"