Domanda

Sto progettando un semplice framework interno per la gestione dei dati delle serie temporali. Dato che LINQ è il mio attuale martello giocattolo, voglio colpire tutto con esso.

Voglio implementare metodi nella classe TimeSeries (Select (), Where () e così via) in modo da poter usare la sintassi LINQ per gestire i dati delle serie temporali

Alcune cose sono semplici, ad es. (da x in A selezionare x + 10), fornendo una nuova serie storica.

Qual è il miglior progetto di sintassi per combinare due o più serie storiche? (da a in A da b in B selezionare a + b) non è eccezionale, poiché esprime un ciclo nidificato. Forse qualcuno si unisce? Questo dovrebbe corrispondere a join sulla variabile del tempo implicito. (Quello che ho in mente corrisponde alla funzione "zip" di lisp)


MODIFICA: Sono necessari alcuni chiarimenti.

Una serie storica è un tipo di funzione che dipende dal tempo, ad es. quotazioni di borsa. Una combinazione di serie storiche potrebbe essere la differenza tra due prezzi delle azioni, in funzione del tempo.

Stock1.MyJoin(Stock2, (a,b)=>a-b)

è possibile, ma può essere espresso in modo ordinato usando una sintassi LINQ? Mi aspetto di implementare personalmente i metodi LINQ nella classe MyTimeSeries .

È stato utile?

Soluzione

Se capisco correttamente la domanda, vuoi unire più sequenze in base alla loro posizione all'interno della sequenza?

Non c'è nulla nella classe System.Linq.Enumerable per farlo poiché entrambi i metodi Join e GroupJoin sono basati su unisci le chiavi. Tuttavia, per coincidenza ho scritto un metodo PositionalJoin solo per questo scopo qualche giorno fa, usato come nel tuo esempio:

sequenceA.PositionalJoin(sequenceB, (a, b) => new { a, b });

La semantica del metodo mostrato di seguito è che non richiede che le sequenze abbiano la stessa lunghezza, ma sarebbe banale modificarlo per richiederlo. Ho anche commentato dove dovrebbe essere la verifica dell'argomento come stava usando le nostre classi helper interne.

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);
    }
}

Non sono sicuro se questo è esattamente quello che stai cercando, ma spero di avere qualche aiuto.

Altri suggerimenti

Union sembra la strada giusta da percorrere - nessun supporto per le espressioni di query, ma penso che esprima ciò che intendi.

Potresti essere interessato a guardare le classi basate su Range in MiscUtil che può essere ben usato per volte. In combinazione con un po 'di divertente metodo di estensione, puoi fare:

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

Non sto suggerendo che questo dovrebbe sostituire qualsiasi cosa tu stia facendo, solo che potresti essere in grado di prendere alcune idee per renderlo ancora più ordinato. Sentiti libero di contribuire anche tu :)

Dal mio progetto 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);
    }
}

La sintassi è:

Stock1.Zip(Stock2, (a,b)=>a-b)

Bjarke, dai un'occhiata a NEsper, è un'app di elaborazione di eventi complessi open source che, tra l'altro, esegue query su serie temporali simili a SQL. Puoi imparare come l'hanno fatto o magari anche sfruttare il loro codice per raggiungere il tuo obiettivo. link qui http://esper.codehaus.org/about/nesper/nesper.html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top