-
04-07-2019 - |
题
我正在设计一个简单的内部框架来处理时间序列数据。鉴于 LINQ 是我目前的玩具锤子,我想用它敲击所有东西。
我想实现类 TimeSeries 中的方法(Select()、Where() 等),以便我可以使用 LINQ 语法来处理时间序列数据
有些事情是直接的,例如(从 A 中的 x 选择 x+10),给出一个新的时间序列。
组合两个或多个时间序列的最佳语法设计是什么?(from a in A from b in B select a+b) 不太好,因为它表达了一个嵌套循环。也许有人加入?这应该对应于隐式时间变量上的连接。(我想到的对应于 lisp 'zip' 函数)
编辑: 有必要进行一些澄清。
时间序列是一种依赖于时间的函数,例如股票报价。时间序列的组合可以是两个股票价格之间的差异,作为时间的函数。
Stock1.MyJoin(Stock2, (a,b)=>a-b)
是可能的,但是可以使用一些 LINQ 语法来简洁地表达吗?我期望在中实现 LINQ 方法 class MyTimeSeries
我。
解决方案
如果我正确理解了这个问题,你想根据它们在序列中的位置加入多个序列吗?
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
听起来像是正确的方法 - 没有查询表达式支持,但我认为它表达了你的意思。
您可能有兴趣查看基于范围的类 杂项工具 可以多次使用。结合一些扩展方法的乐趣,你可以这样做:
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