Выражение для проверки того, что все элементы в последовательности одинаковы

Есть ли где-нибудь шаблон с несколькими экземплярами в 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;...], но я не могу понять, как сопоставить этот последний шаблон. Это возможно? Или есть лучший подход, который я мог бы использовать? Я нигде не нашел ничего о повторяющемся шаблоне.


person Onorio Catenacci    schedule 29.10.2009    source источник


Ответы (3)


Я не знаю ни одного шаблона, который делает то, что вы хотите, но вы можете сделать это:

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!"

Имейте в виду, что производительность этой функции может быть хуже, чем у функции, основанной на списке.

person cfern    schedule 29.10.2009
comment
@cfern, ты прав. Мне нужно быть осторожным с терминологией, которую я использую. Я склонен использовать List и Sequence как синонимы, а в F# они точно не синонимы. Я работаю со списком. - person Onorio Catenacci; 29.10.2009

Вот решение, использующее активные шаблоны с несколькими регистрами.

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"
person m-sharp    schedule 01.11.2009

Я бы рассмотрел возможность выполнения одного из следующих действий:


yourSequence |> Seq.windowed(2) |> Seq.forall(fun arr -> arr.[0] = arr.[1])

or


let h = Seq.hd yourSequence
yourSequence |> Seq.forall((=) h)

Всегда полезно использовать библиотечные функции, когда это возможно;)

person em70    schedule 31.10.2009