“参加”時系列の
-
04-07-2019 - |
質問
時系列データを処理するための簡単な内部フレームワークを設計しています。 LINQが私の現在のおもちゃのハンマーであることを考えると、それですべてを叩きたいです。
LINQ構文を使用して時系列データを処理できるように、クラスTimeSeries(Select()、Where()など)のメソッドを実装したい
いくつかのことは簡単です。 (Aのxからx + 10を選択)、新しい時系列を提供します。
2つ以上の時系列を組み合わせるのに最適な構文設計は何ですか? (AのaからBのbから、a + bを選択)は、ネストされたループを表すので、あまり良くありません。 たぶん参加しますか?これは、暗黙的な時間変数の結合に対応する必要があります。 (私が念頭に置いているのは、lisp「zip」機能に対応しています)
編集: いくつかの説明が必要です。
時系列は、時間に依存する一種の機能です。株価。 時系列の組み合わせは、時間の関数として、2つの株価の差になる可能性があります。
Stock1.MyJoin(Stock2, (a,b)=>a-b)
は可能ですが、これはいくつかのLINQ構文を使用してきれいに表現できますか?
自分で class MyTimeSeries
にLINQメソッドを実装することを期待しています。
解決
質問を正しく理解している場合、シーケンス内の位置に基づいて複数のシーケンスを結合しますか?
System.Linq.Enumerable
クラスには、 Join
メソッドと GroupJoin
メソッドの両方が基づいているため、これを行うものはありません。結合キー。ただし、偶然にも、数日前のこの目的のために PositionalJoin
メソッドを作成しました。これは例のように使用されます。
sequenceA.PositionalJoin(sequenceB, (a, b) => new { a, b });
以下に示すメソッドのセマンティクスでは、シーケンスの長さを等しくする必要はありませんが、これを必要とするように変更するのは簡単です。また、内部ヘルパークラスを使用していたため、引数のチェックが必要な場所をコメントアウトしました。
public static IEnumerable<TResult> PositionalJoin<T1, T2, TResult>(
this IEnumerable<T1> source1,
IEnumerable<T2> source2,
Func<T1, T2, int, TResult> selector)
{
// argument checking here
return PositionalJoinIterator(source1, source2, selector);
}
private static IEnumerable<TResult> PositionalJoinIterator<T1, T2, TResult>(
IEnumerable<T1> source1,
IEnumerable<T2> source2,
Func<T1, T2, TResult> selector)
{
using (var enumerator1 = source1.GetEnumerator())
using (var enumerator2 = source2.GetEnumerator())
{
bool gotItem;
do
{
gotItem = false;
T1 item1;
if (enumerator1.MoveNext())
{
item1 = enumerator1.Current;
gotItem = true;
}
else
{
item1 = default(T1);
}
T2 item2;
if (enumerator2.MoveNext())
{
item2 = enumerator2.Current;
gotItem = true;
}
else
{
item2 = default(T2);
}
if (gotItem)
{
yield return selector(item1, item2);
}
}
while (gotItem);
}
}
これがまさにあなたが探しているものかどうかはわかりませんが、うまくいけば助けになるでしょう。
他のヒント
Union
は正しい方法のように聞こえます-クエリ式のサポートはありませんが、それはあなたの意味を表していると思います。
MiscUtil の範囲ベースのクラスを見ることに興味があるかもしれません。うまく使用できます。拡張メソッドのちょっとした楽しみと組み合わせて、次のことができます。
foreach (DateTime day in 19.June(1976).To(DateTime.Today).Step(1.Day()))
{
Console.WriteLine("I'm alive!");
}
これはあなたがやっていることを置き換えることを提案するものではありません。ただあなたがそれをよりきれいにするためにいくつかのアイデアをとることができるかもしれません。遠慮なくご協力ください:)
NExtension プロジェクトから:
public static IEnumerable<TResult> Zip<T1, T2, TResult>(
this IEnumerable<T1> source1,
IEnumerable<T2> source2,
Func<T1, T2, TResult> combine)
{
if (source1 == null)
throw new ArgumentNullException("source1");
if (source2 == null)
throw new ArgumentNullException("source2");
if (combine == null)
throw new ArgumentNullException("combine");
IEnumerator<T1> data1 = source1.GetEnumerator();
IEnumerator<T2> data2 = source2.GetEnumerator();
while (data1.MoveNext() && data2.MoveNext())
{
yield return combine(data1.Current, data2.Current);
}
}
構文は次のとおりです:
Stock1.Zip(Stock2, (a,b)=>a-b)
Bjarke、NEsperを見てください。これは、特にSQLのような時系列クエリを実行するオープンソースの複合イベント処理アプリです。あなたは彼らがそれをどのようにしたかを学ぶか、あるいはおそらくあなたの目標を達成するために彼らのコードを活用することさえできます。ここにリンク http://esper.codehaus.org/about/nesper/nesper.html