3

我正在设计一个简单的内部框架来处理时间序列数据。鉴于 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

4

4 回答 4

1

Union听起来是正确的方法 - 不支持查询表达式,但我认为它表达了你的意思。

您可能有兴趣查看MiscUtil中基于 Range 的类,这些类可以很好地使用。结合一点扩展方法的乐趣,你可以做到:

foreach (DateTime day in 19.June(1976).To(DateTime.Today).Step(1.Day()))
{
    Console.WriteLine("I'm alive!");
}

我并不是建议这应该取代你正在做的任何事情,只是你可以采取一些想法让它变得更整洁。也可以随意回馈:)

于 2008-10-27T21:38:20.533 回答
1

从我的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)
于 2008-10-27T22:27:35.893 回答
1

Bjarke,看看 NEsper,它是一个开源的复杂事件处理应用程序,其中包括类似 SQL 的时间序列查询。您可以了解他们是如何做到的,或者甚至可以利用他们的代码来实现您的目标。链接在这里http://esper.codehaus.org/about/nesper/nesper.html

于 2008-10-27T22:31:29.393 回答
0

如果我正确理解了这个问题,您想根据它们在序列中的位置加入多个序列吗?

类中没有任何东西System.Linq.Enumerable可以做到这一点,因为JoinGroupJoin方法都是基于连接键的。但是,巧合的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);
    }
}

不确定这是否正是您正在寻找的,但希望能有所帮助。

于 2008-10-27T22:15:09.367 回答