Выражение для проверки того, что все элементы в последовательности одинаковы
-
10-07-2019 - |
Вопрос
Есть ли где-нибудь в F # шаблон с несколькими экземплярами?
Считайте, что я работаю над списком.У меня есть следующее соответствие шаблону
match l with
| [] | [_] -> l //if the list is empty or contains only one item, simply return it
|
//is there a pattern to test if all of the elements are identical?
Другими словами, передача [] или [1] должна просто вернуть список, как и [1;1;1;...], но я не могу понять, как сопоставить этот последний шаблон.Это возможно?Или есть лучший подход, который я мог бы использовать?Я нигде не нашел ничего о повторяющийся шаблон.
Решение
Я не знаю ни одного шаблона, который делал бы то, что вы хотите, но вы могли бы сделать это:
let allSame L =
match L with
| [] | [_] -> L
| h::t when t |> List.forall ((=) h) -> L
| _ -> failwith "unpossible!" //handle the failing match here
P.S.Вы говорите о последовательности, но совпадение указывает на то, что вы работаете со списком.Соответствующий код последовательности будет выглядеть примерно так:
let allSameSeq s =
match Seq.length s with
| 0 | 1 -> s
| _ when Seq.skip 1 s |> Seq.forall ((=) (Seq.head s)) -> s
| _ -> failwith "unpossible!"
Имейте в виду, что производительность этой функции вполне может быть хуже, чем у функции на основе списка.
Другие советы
Вот решение, использующее активные шаблоны с несколькими случаями. Р>
let (|SingleOrEmpty|AllIdentical|Neither|) (lst:'a list) =
if lst.Length < 2 then
SingleOrEmpty
elif List.forall (fun elem -> elem = lst.[0]) lst then
AllIdentical
else
Neither
let allElementsIdentical lst:'a list =
match lst with
|SingleOrEmpty|AllIdentical -> lst
|Neither -> failwith "Not a suitable list"
Я бы рассмотрел возможность выполнения одного из следующих действий:
yourSequence |> Seq.windowed(2) |> Seq.forall(fun arr -> arr.[0] = arr.[1])
или
let h = Seq.hd yourSequence
yourSequence |> Seq.forall((=) h)
Всегда полезно использовать библиотечные функции, когда это возможно;)