シーケンス内のすべてのアイテムが同じであることをテストする式
-
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
PSあなたはシーケンスについて話しているが、あなたのマッチはあなたがリストで作業していることを示している。シーケンスに対応するコードは次のようになります
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)
可能な場合はライブラリ関数を使用するのが常に良い;)
所属していません StackOverflow