Feedback

C# - Linq: Die Guten ins Töpfchen, die Schlechten ...

Veröffentlicht von am 27.11.2014
(2 Bewertungen)
Die .Where()-Funktion ist richtig klasse und ich setze sie in meinem Code oft ein.

Manchmal brauche ich aber beides, das Resultat von .Where() und den Rest, der übrig bleibt.

Deshalb habe ich mir ein .Split()-Funktion geschrieben.

Da ich nicht auf die Delayed Execution von Linq angewiesen bin, benutze ich die performantere .Split()-Funktion.

Wer aber möchte, kann die .SplitDelayed()-Funktion benutzen, die erst ausgeführt wird (wie bei allen Linq-Sachen), sobald ein Enumerator angefordert wird (z.B. bei foreach).
GFU-Schulungen  [Anzeige]

VB.NET Komplett

Sie stehen vo der Aufgabe, individuelle Anwendungen für Windows zu schreiben. Hier ist VB.NET die optimale Sprache. Sie erlernt sich recht leicht und passt sich komplett in die .NET Umgebung von Microsoft ein. Nach der Schulung entwickeln Sie anwenderfreundliche Programme in VB.NET . Mit den objektorientierten Modellen in VB.NET erzeugen Sie außerdem wiederverwendbare Komponenten.

VB.NET Aufbau

Sie verfügen nach der Schulung über fundierte Kenntnisse in der Arbeit mit objektorientierten Modellen in VB.NET und können wiederverwendbare Komponenten eigenständig erzeugen.

public static class LinqHelper
{
    /// <summary>
    /// Splits a collection into two lists based on the given true/false evaluation.
    /// 
    /// Note: This method resolves the query at once for performance considerations.
    ///       It does not use delayed execution!
    /// </summary>
    /// <typeparam name="T">the type of the list items</typeparam>
    /// <param name="inList">the original list</param>
    /// <param name="predicate">the function delegate to the evaluator</param>
    /// <param name="trueList">the true results</param>
    /// <param name="falseList">the false results</param>
    public static void Split<T>(this IEnumerable<T> inList
        , Func<T, Boolean> predicate
        , out IEnumerable<T> trueList
        , out IEnumerable<T> falseList)
    {
        //The .ToList() is deliberately here
        //otherwise the predicate would always be checked twice.
        //First when the user of the method iterates over the trueList
        //Second when the user of the method iterates over the falseList
        trueList = inList.Where(predicate).ToList();
        falseList = inList.Except(trueList).ToList();
    }

    /// <summary>
    /// Splits a collection into two lists based on the given true/false evaluation
    /// </summary>
    /// <typeparam name="T">the type of the list items</typeparam>
    /// <param name="inList">the original list</param>
    /// <param name="predicate">the function delegate to the evaluator</param>
    /// <param name="trueList">the true results</param>
    /// <param name="falseList">the false results</param>
    public static void SplitDelayed<T>(this IEnumerable<T> inList
        , Func<T, Boolean> predicate
        , out IEnumerable<T> trueList
        , out IEnumerable<T> falseList)
    {
        trueList = inList.Where(predicate);
        falseList = inList.Except(trueList);
    }
}


static class Demo
{
    static void Main()
    {
        SplitDemo();
    }

    private static void SplitDemo()
    {
        List<Int32> list;
        IEnumerable<Int32> odds;
        IEnumerable<Int32> evens;
        const Int32 Max = 10000000;

        list = new List<Int32>(Max);
        for (Int32 i = 1; i <= Max; i++)
        {
            list.Add(i);
        }

        list.SplitDelayed(number => ((number % 2) == 0), out evens, out odds);
        Output(odds, evens);
        Console.WriteLine();
        Output(odds.ToList(), evens.ToList());
        Console.WriteLine();

        list.Split(number => ((number % 2) == 0), out evens, out odds);
        Output(odds, evens);
        Console.WriteLine();
        Output(odds.ToList(), evens.ToList());
        Console.WriteLine();

        Console.WriteLine("Done.");
        Console.ReadLine();
    }

    private static void Output(IEnumerable<Int32> odds
        , IEnumerable<Int32> evens)
    {
        for (Int32 i = 0; i < 10; i++)
        {
            DateTime start;
            DateTime end;
            TimeSpan span;

            start = DateTime.UtcNow;
            foreach (Int32 even in evens)
            { }
            foreach (Int32 odd in odds)
            { }
            end = DateTime.UtcNow;
            span = new TimeSpan(end.Ticks - start.Ticks);
            Console.WriteLine(span.Seconds 
                + "." + span.Milliseconds.ToString("000"));
        }
    }
}
Abgelegt unter where, except, split, linq.

4 Kommentare zum Snippet

Koopakiller schrieb am 27.11.2014:
Sicherlich oftmals eine Vereinfachung. Du solltest das mit dem ToList allerdings auch in die XML Doku hinein schreiben.
Grundsätzlich kann man die verzögerte Ausführung nämlich von fast allen LINQ Methoden erwarten, sodass man eine Abweichung wenigstens erwähnen sollte.
DJ Doena schrieb am 28.11.2014:
@Koopakiller: XML Kommentar angepasst
Jan Welker schrieb am 28.11.2014:
Gute Idee! Die Anforderung hatte ich auch schon einige mal, hab mir aber nie was generisches gebaut.
Koopakiller schrieb am 28.11.2014:
Da gab es jetzt auch die 5 Sterne :)
 

Logge dich ein, um hier zu kommentieren!