私はたまたま時系列データを操作するためのライブラリに取り組んでおり、これを行うための関数がありますDateTime * float option * float option
.1つの系列が指定された日付の値を持つ場合を表すために返されるため、実際にはもう少し一般的ですが、他のものはしません。
この関数は、2 つのシリーズが既に並べ替えられていることを前提としています。つまり、それらを 1 回だけ走査する必要があります (並べ替えられていないシーケンスについては、複数の反復を行うか、いくつかの一時テーブルを作成する必要があります)。
また、例よりも引数が交換されていることに注意してください。あなたはそれを与える必要がありますDateTime * float
。この関数は特に優れているわけではありませんIEnumerable
。つまり、変更可能な列挙子 (および一般的に醜い命令型のもの) を使用する必要があるという意味で機能します。一般に、パターン マッチングはシーケンスではうまく機能しません。headは取得できますが、 tailは取得できません。これは効率が悪いためです。F# のリストにはもっといいものを書くことができます...
open System.Collections.Generic
let alignWithOrdering (seq1:seq<'T * 'TAddress>) (seq2:seq<'T * 'TAddress>) (comparer:IComparer<_>) = seq {
let withIndex seq = Seq.mapi (fun i v -> i, v) seq
use en1 = seq1.GetEnumerator()
use en2 = seq2.GetEnumerator()
let en1HasNext = ref (en1.MoveNext())
let en2HasNext = ref (en2.MoveNext())
let returnAll (en:IEnumerator<_>) hasNext f = seq {
if hasNext then
yield f en.Current
while en.MoveNext() do yield f en.Current }
let rec next () = seq {
if not en1HasNext.Value then yield! returnAll en2 en2HasNext.Value (fun (k, i) -> k, None, Some i)
elif not en2HasNext.Value then yield! returnAll en1 en1HasNext.Value (fun (k, i) -> k, Some i, None)
else
let en1Val, en2Val = fst en1.Current, fst en2.Current
let comparison = comparer.Compare(en1Val, en2Val)
if comparison = 0 then
yield en1Val, Some(snd en1.Current), Some(snd en2.Current)
en1HasNext := en1.MoveNext()
en2HasNext := en2.MoveNext()
yield! next()
elif comparison < 0 then
yield en1Val, Some(snd en1.Current), None
en1HasNext := en1.MoveNext()
yield! next ()
else
yield en2Val, None, Some(snd en2.Current)
en2HasNext := en2.MoveNext()
yield! next () }
yield! next () }
文字列を (あなたの ではなく) キーとして使いたいと仮定するとDateTime
、次のように呼び出すことができます:
alignWithOrdering
[ ("b", 0); ("c", 1); ("d", 2) ]
[ ("a", 0); ("b", 1); ("c", 2) ] (Comparer<string>.Default) |> List.ofSeq
// Returns
[ ("a", None, Some 0); ("b", Some 0, Some 1);
("c", Some 1, Some 2); ("d", Some 2, None) ]
F# で株式データの時系列を操作することに興味がある場合は、 F# FoundationのF# for Data and Machine Learningワーキング グループに参加することに興味があるかもしれません。私たちは現在、時系列をサポートするオープンソース ライブラリに取り組んでいます。初期プレビューを確認して貢献することに興味がある場合は、このワーキング グループを通じて行うことができます。